PostgreSQL Source Code git master
Loading...
Searching...
No Matches
tab-complete.in.c
Go to the documentation of this file.
1/*
2 * psql - the PostgreSQL interactive terminal
3 *
4 * Copyright (c) 2000-2026, PostgreSQL Global Development Group
5 *
6 * src/bin/psql/tab-complete.in.c
7 *
8 * Note: this will compile and work as-is if SWITCH_CONVERSION_APPLIED
9 * is not defined. However, the expected usage is that it's first run
10 * through gen_tabcomplete.pl, which will #define that symbol, fill in the
11 * tcpatterns[] array, and convert the else-if chain in match_previous_words()
12 * into a switch. See comments for match_previous_words() and the header
13 * comment in gen_tabcomplete.pl for more detail.
14 */
15
16/*----------------------------------------------------------------------
17 * This file implements a somewhat more sophisticated readline "TAB
18 * completion" in psql. It is not intended to be AI, to replace
19 * learning SQL, or to relieve you from thinking about what you're
20 * doing. Also it does not always give you all the syntactically legal
21 * completions, only those that are the most common or the ones that
22 * the programmer felt most like implementing.
23 *
24 * CAVEAT: Tab completion causes queries to be sent to the backend.
25 * The number of tuples returned gets limited, in most default
26 * installations to 1000, but if you still don't like this prospect,
27 * you can turn off tab completion in your ~/.inputrc (or else
28 * ${INPUTRC}) file so:
29 *
30 * $if psql
31 * set disable-completion on
32 * $endif
33 *
34 * See `man 3 readline' or `info readline' for the full details.
35 *
36 * BUGS:
37 * - Quotes, parentheses, and other funny characters are not handled
38 * all that gracefully.
39 *----------------------------------------------------------------------
40 */
41
42#include "postgres_fe.h"
43
44#include "input.h"
45#include "tab-complete.h"
46
47/* If we don't have this, we might as well forget about the whole thing: */
48#ifdef USE_READLINE
49
50#include <ctype.h>
51#include <sys/stat.h>
52
53#include "catalog/pg_am_d.h"
54#include "catalog/pg_class_d.h"
55#include "common.h"
56#include "common/keywords.h"
57#include "libpq-fe.h"
58#include "mb/pg_wchar.h"
59#include "pqexpbuffer.h"
60#include "settings.h"
61#include "stringutils.h"
62
63/*
64 * Ancient versions of libedit provide filename_completion_function()
65 * instead of rl_filename_completion_function(). Likewise for
66 * [rl_]completion_matches().
67 */
68#ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
69#define rl_filename_completion_function filename_completion_function
70#endif
71
72#ifndef HAVE_RL_COMPLETION_MATCHES
73#define rl_completion_matches completion_matches
74#endif
75
76/*
77 * Currently we assume that rl_filename_dequoting_function exists if
78 * rl_filename_quoting_function does. If that proves not to be the case,
79 * we'd need to test for the former, or possibly both, in configure.
80 */
81#ifdef HAVE_RL_FILENAME_QUOTING_FUNCTION
82#define USE_FILENAME_QUOTING_FUNCTIONS 1
83#endif
84
85/* word break characters */
86#define WORD_BREAKS "\t\n@><=;|&() "
87
88/*
89 * Since readline doesn't let us pass any state through to the tab completion
90 * callback, we have to use this global variable to let get_previous_words()
91 * get at the previous lines of the current command. Ick.
92 */
94
95/*
96 * In some situations, the query to find out what names are available to
97 * complete with must vary depending on server version. We handle this by
98 * storing a list of queries, each tagged with the minimum server version
99 * it will work for. Each list must be stored in descending server version
100 * order, so that the first satisfactory query is the one to use.
101 *
102 * When the query string is otherwise constant, an array of VersionedQuery
103 * suffices. Terminate the array with an entry having min_server_version = 0.
104 * That entry's query string can be a query that works in all supported older
105 * server versions, or NULL to give up and do no completion.
106 */
107typedef struct VersionedQuery
108{
110 const char *query;
112
113/*
114 * This struct is used to define "schema queries", which are custom-built
115 * to obtain possibly-schema-qualified names of database objects. There is
116 * enough similarity in the structure that we don't want to repeat it each
117 * time. So we put the components of each query into this struct and
118 * assemble them with the common boilerplate in _complete_from_query().
119 *
120 * We also use this struct to define queries that use completion_ref_object,
121 * which is some object related to the one(s) we want to get the names of
122 * (for example, the table we want the indexes of). In that usage the
123 * objects we're completing might not have a schema of their own, but the
124 * reference object almost always does (passed in completion_ref_schema).
125 *
126 * As with VersionedQuery, we can use an array of these if the query details
127 * must vary across versions.
128 */
129typedef struct SchemaQuery
130{
131 /*
132 * If not zero, minimum server version this struct applies to. If not
133 * zero, there should be a following struct with a smaller minimum server
134 * version; use catname == NULL in the last entry if we should do nothing.
135 */
137
138 /*
139 * Name of catalog or catalogs to be queried, with alias(es), eg.
140 * "pg_catalog.pg_class c". Note that "pg_namespace n" and/or
141 * "pg_namespace nr" will be added automatically when needed.
142 */
143 const char *catname;
144
145 /*
146 * Selection condition --- only rows meeting this condition are candidates
147 * to display. If catname mentions multiple tables, include the necessary
148 * join condition here. For example, this might look like "c.relkind = "
149 * CppAsString2(RELKIND_RELATION). Write NULL (not an empty string) if
150 * not needed.
151 */
152 const char *selcondition;
153
154 /*
155 * Visibility condition --- which rows are visible without schema
156 * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
157 * NULL if not needed.
158 */
159 const char *viscondition;
160
161 /*
162 * Namespace --- name of field to join to pg_namespace.oid when there is
163 * schema qualification. For example, "c.relnamespace". NULL if we don't
164 * want to join to pg_namespace (then any schema part in the input word
165 * will be ignored).
166 */
167 const char *namespace;
168
169 /*
170 * Result --- the base object name to return. For example, "c.relname".
171 */
172 const char *result;
173
174 /*
175 * In some cases, it's difficult to keep the query from returning the same
176 * object multiple times. Specify use_distinct to filter out duplicates.
177 */
178 bool use_distinct;
179
180 /*
181 * Additional literal strings (usually keywords) to be offered along with
182 * the query results. Provide a NULL-terminated array of constant
183 * strings, or NULL if none.
184 */
185 const char *const *keywords;
186
187 /*
188 * If this query uses completion_ref_object/completion_ref_schema,
189 * populate the remaining fields, else leave them NULL. When using this
190 * capability, catname must include the catalog that defines the
191 * completion_ref_object, and selcondition must include the join condition
192 * that connects it to the result's catalog.
193 *
194 * refname is the field that should be equated to completion_ref_object,
195 * for example "cr.relname".
196 */
197 const char *refname;
198
199 /*
200 * Visibility condition to use when completion_ref_schema is not set. For
201 * example, "pg_catalog.pg_table_is_visible(cr.oid)". NULL if not needed.
202 */
203 const char *refviscondition;
204
205 /*
206 * Name of field to join to pg_namespace.oid when completion_ref_schema is
207 * set. For example, "cr.relnamespace". NULL if we don't want to
208 * consider completion_ref_schema.
209 */
210 const char *refnamespace;
212
213
214/* Store maximum number of records we want from database queries
215 * (implemented via SELECT ... LIMIT xx).
216 */
217static int completion_max_records;
218
219/*
220 * Communication variables set by psql_completion (mostly in COMPLETE_WITH_FOO
221 * macros) and then used by the completion callback functions. Ugly but there
222 * is no better way.
223 */
224static char completion_last_char; /* last char of input word */
225static const char *completion_charp; /* to pass a string */
226static const char *const *completion_charpp; /* to pass a list of strings */
227static const VersionedQuery *completion_vquery; /* to pass a VersionedQuery */
228static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
229static char *completion_ref_object; /* name of reference object */
230static char *completion_ref_schema; /* schema name of reference object */
231static bool completion_case_sensitive; /* completion is case sensitive */
232static bool completion_verbatim; /* completion is verbatim */
233static bool completion_force_quote; /* true to force-quote filenames */
234
235/*
236 * A few macros to ease typing. You can use these to complete the given
237 * string with
238 * 1) The result from a query you pass it. (Perhaps one of those below?)
239 * We support both simple and versioned queries.
240 * 2) The result from a schema query you pass it.
241 * We support both simple and versioned schema queries.
242 * 3) The items from a null-pointer-terminated list (with or without
243 * case-sensitive comparison); if the list is constant you can build it
244 * with COMPLETE_WITH() or COMPLETE_WITH_CS(). The QUERY_LIST and
245 * QUERY_PLUS forms combine such literal lists with a query result.
246 * 4) The list of attributes of the given table (possibly schema-qualified).
247 * 5) The list of arguments to the given function (possibly schema-qualified).
248 *
249 * The query is generally expected to return raw SQL identifiers; matching
250 * to what the user typed is done in a quoting-aware fashion. If what is
251 * returned is not SQL identifiers, use one of the VERBATIM forms, in which
252 * case the query results are matched to the user's text without double-quote
253 * processing (so if quoting is needed, you must provide it in the query
254 * results).
255 */
256#define COMPLETE_WITH_QUERY(query) \
257 COMPLETE_WITH_QUERY_LIST(query, NULL)
258
259#define COMPLETE_WITH_QUERY_LIST(query, list) \
260do { \
261 completion_charp = query; \
262 completion_charpp = list; \
263 completion_verbatim = false; \
264 matches = rl_completion_matches(text, complete_from_query); \
265} while (0)
266
267#define COMPLETE_WITH_QUERY_PLUS(query, ...) \
268do { \
269 static const char *const list[] = { __VA_ARGS__, NULL }; \
270 COMPLETE_WITH_QUERY_LIST(query, list); \
271} while (0)
272
273#define COMPLETE_WITH_QUERY_VERBATIM(query) \
274 COMPLETE_WITH_QUERY_VERBATIM_LIST(query, NULL)
275
276#define COMPLETE_WITH_QUERY_VERBATIM_LIST(query, list) \
277do { \
278 completion_charp = query; \
279 completion_charpp = list; \
280 completion_verbatim = true; \
281 matches = rl_completion_matches(text, complete_from_query); \
282} while (0)
283
284#define COMPLETE_WITH_QUERY_VERBATIM_PLUS(query, ...) \
285do { \
286 static const char *const list[] = { __VA_ARGS__, NULL }; \
287 COMPLETE_WITH_QUERY_VERBATIM_LIST(query, list); \
288} while (0)
289
290#define COMPLETE_WITH_VERSIONED_QUERY(query) \
291 COMPLETE_WITH_VERSIONED_QUERY_LIST(query, NULL)
292
293#define COMPLETE_WITH_VERSIONED_QUERY_LIST(query, list) \
294do { \
295 completion_vquery = query; \
296 completion_charpp = list; \
297 completion_verbatim = false; \
298 matches = rl_completion_matches(text, complete_from_versioned_query); \
299} while (0)
300
301#define COMPLETE_WITH_VERSIONED_QUERY_PLUS(query, ...) \
302do { \
303 static const char *const list[] = { __VA_ARGS__, NULL }; \
304 COMPLETE_WITH_VERSIONED_QUERY_LIST(query, list); \
305} while (0)
306
307#define COMPLETE_WITH_SCHEMA_QUERY(query) \
308 COMPLETE_WITH_SCHEMA_QUERY_LIST(query, NULL)
309
310#define COMPLETE_WITH_SCHEMA_QUERY_LIST(query, list) \
311do { \
312 completion_squery = &(query); \
313 completion_charpp = list; \
314 completion_verbatim = false; \
315 matches = rl_completion_matches(text, complete_from_schema_query); \
316} while (0)
317
318#define COMPLETE_WITH_SCHEMA_QUERY_PLUS(query, ...) \
319do { \
320 static const char *const list[] = { __VA_ARGS__, NULL }; \
321 COMPLETE_WITH_SCHEMA_QUERY_LIST(query, list); \
322} while (0)
323
324#define COMPLETE_WITH_SCHEMA_QUERY_VERBATIM(query) \
325do { \
326 completion_squery = &(query); \
327 completion_charpp = NULL; \
328 completion_verbatim = true; \
329 matches = rl_completion_matches(text, complete_from_schema_query); \
330} while (0)
331
332#define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(query) \
333 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, NULL)
334
335#define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, list) \
336do { \
337 completion_squery = query; \
338 completion_charpp = list; \
339 completion_verbatim = false; \
340 matches = rl_completion_matches(text, complete_from_versioned_schema_query); \
341} while (0)
342
343#define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_PLUS(query, ...) \
344do { \
345 static const char *const list[] = { __VA_ARGS__, NULL }; \
346 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(query, list); \
347} while (0)
348
349/*
350 * Caution: COMPLETE_WITH_CONST is not for general-purpose use; you probably
351 * want COMPLETE_WITH() with one element, instead.
352 */
353#define COMPLETE_WITH_CONST(cs, con) \
354do { \
355 completion_case_sensitive = (cs); \
356 completion_charp = (con); \
357 matches = rl_completion_matches(text, complete_from_const); \
358} while (0)
359
360#define COMPLETE_WITH_LIST_INT(cs, list) \
361do { \
362 completion_case_sensitive = (cs); \
363 completion_charpp = (list); \
364 matches = rl_completion_matches(text, complete_from_list); \
365} while (0)
366
367#define COMPLETE_WITH_LIST(list) COMPLETE_WITH_LIST_INT(false, list)
368#define COMPLETE_WITH_LIST_CS(list) COMPLETE_WITH_LIST_INT(true, list)
369
370#define COMPLETE_WITH(...) \
371do { \
372 static const char *const list[] = { __VA_ARGS__, NULL }; \
373 COMPLETE_WITH_LIST(list); \
374} while (0)
375
376#define COMPLETE_WITH_CS(...) \
377do { \
378 static const char *const list[] = { __VA_ARGS__, NULL }; \
379 COMPLETE_WITH_LIST_CS(list); \
380} while (0)
381
382#define COMPLETE_WITH_ATTR(relation) \
383 COMPLETE_WITH_ATTR_LIST(relation, NULL)
384
385#define COMPLETE_WITH_ATTR_LIST(relation, list) \
386do { \
387 set_completion_reference(relation); \
388 completion_squery = &(Query_for_list_of_attributes); \
389 completion_charpp = list; \
390 completion_verbatim = false; \
391 matches = rl_completion_matches(text, complete_from_schema_query); \
392} while (0)
393
394#define COMPLETE_WITH_ATTR_PLUS(relation, ...) \
395do { \
396 static const char *const list[] = { __VA_ARGS__, NULL }; \
397 COMPLETE_WITH_ATTR_LIST(relation, list); \
398} while (0)
399
400/*
401 * libedit will typically include the literal's leading single quote in
402 * "text", while readline will not. Adapt our offered strings to fit.
403 * But include a quote if there's not one just before "text", to get the
404 * user off to the right start.
405 */
406#define COMPLETE_WITH_ENUM_VALUE(type) \
407do { \
408 set_completion_reference(type); \
409 if (text[0] == '\'' || \
410 start == 0 || rl_line_buffer[start - 1] != '\'') \
411 completion_squery = &(Query_for_list_of_enum_values_quoted); \
412 else \
413 completion_squery = &(Query_for_list_of_enum_values_unquoted); \
414 completion_charpp = NULL; \
415 completion_verbatim = true; \
416 matches = rl_completion_matches(text, complete_from_schema_query); \
417} while (0)
418
419/*
420 * Timezone completion is mostly like enum label completion, but we work
421 * a little harder since this is a more common use-case.
422 */
423#define COMPLETE_WITH_TIMEZONE_NAME() \
424do { \
425 static const char *const list[] = { "DEFAULT", NULL }; \
426 if (text[0] == '\'') \
427 completion_charp = Query_for_list_of_timezone_names_quoted_in; \
428 else if (start == 0 || rl_line_buffer[start - 1] != '\'') \
429 completion_charp = Query_for_list_of_timezone_names_quoted_out; \
430 else \
431 completion_charp = Query_for_list_of_timezone_names_unquoted; \
432 completion_charpp = list; \
433 completion_verbatim = true; \
434 matches = rl_completion_matches(text, complete_from_query); \
435} while (0)
436
437#define COMPLETE_WITH_FUNCTION_ARG(function) \
438do { \
439 set_completion_reference(function); \
440 completion_squery = &(Query_for_list_of_arguments); \
441 completion_charpp = NULL; \
442 completion_verbatim = true; \
443 matches = rl_completion_matches(text, complete_from_schema_query); \
444} while (0)
445
446#define COMPLETE_WITH_FILES_LIST(escape, force_quote, list) \
447do { \
448 completion_charp = escape; \
449 completion_charpp = list; \
450 completion_force_quote = force_quote; \
451 matches = rl_completion_matches(text, complete_from_files); \
452} while (0)
453
454#define COMPLETE_WITH_FILES(escape, force_quote) \
455 COMPLETE_WITH_FILES_LIST(escape, force_quote, NULL)
456
457#define COMPLETE_WITH_FILES_PLUS(escape, force_quote, ...) \
458do { \
459 static const char *const list[] = { __VA_ARGS__, NULL }; \
460 COMPLETE_WITH_FILES_LIST(escape, force_quote, list); \
461} while (0)
462
463#define COMPLETE_WITH_GENERATOR(generator) \
464 matches = rl_completion_matches(text, generator)
465
466/*
467 * Assembly instructions for schema queries
468 *
469 * Note that toast tables are not included in those queries to avoid
470 * unnecessary bloat in the completions generated.
471 */
472
474 .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_class c1",
475 .selcondition = "con.conrelid=c1.oid",
476 .result = "con.conname",
477 .refname = "c1.relname",
478 .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
479 .refnamespace = "c1.relnamespace",
480};
481
483 .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_class c1",
484 .selcondition = "con.conrelid=c1.oid and not con.convalidated",
485 .result = "con.conname",
486 .refname = "c1.relname",
487 .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
488 .refnamespace = "c1.relnamespace",
489};
490
492 .catname = "pg_catalog.pg_constraint con, pg_catalog.pg_type t",
493 .selcondition = "con.contypid=t.oid",
494 .result = "con.conname",
495 .refname = "t.typname",
496 .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
497 .refnamespace = "t.typnamespace",
498};
499
501 .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i",
502 .selcondition = "c1.oid=i.indrelid and i.indexrelid=c2.oid",
503 .result = "c2.relname",
504 .refname = "c1.relname",
505 .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
506 .refnamespace = "c1.relnamespace",
507};
508
510 .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i",
511 .selcondition = "c1.oid=i.indrelid and i.indexrelid=c2.oid and i.indisunique",
512 .result = "c2.relname",
513 .refname = "c1.relname",
514 .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
515 .refnamespace = "c1.relnamespace",
516};
517
519 {
520 .min_server_version = 110000,
521 .catname = "pg_catalog.pg_proc p",
522 .selcondition = "p.prokind = 'a'",
523 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
524 .namespace = "p.pronamespace",
525 .result = "p.proname",
526 },
527 {
528 .catname = "pg_catalog.pg_proc p",
529 .selcondition = "p.proisagg",
530 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
531 .namespace = "p.pronamespace",
532 .result = "p.proname",
533 }
534};
535
537 .catname = "pg_catalog.pg_proc p",
538 .result = "pg_catalog.oidvectortypes(p.proargtypes)||')'",
539 .refname = "p.proname",
540 .refviscondition = "pg_catalog.pg_function_is_visible(p.oid)",
541 .refnamespace = "p.pronamespace",
542};
543
545 .catname = "pg_catalog.pg_attribute a, pg_catalog.pg_class c",
546 .selcondition = "c.oid = a.attrelid and a.attnum > 0 and not a.attisdropped",
547 .result = "a.attname",
548 .refname = "c.relname",
549 .refviscondition = "pg_catalog.pg_table_is_visible(c.oid)",
550 .refnamespace = "c.relnamespace",
551};
552
554 .catname = "pg_catalog.pg_attribute a, pg_catalog.pg_class c",
555 .selcondition = "c.oid = a.attrelid and a.attnum > 0 and not a.attisdropped",
556 .result = "a.attnum::pg_catalog.text",
557 .refname = "c.relname",
558 .refviscondition = "pg_catalog.pg_table_is_visible(c.oid)",
559 .refnamespace = "c.relnamespace",
560};
561
562static const char *const Keywords_for_list_of_datatypes[] = {
563 "bigint",
564 "boolean",
565 "character",
566 "double precision",
567 "integer",
568 "real",
569 "smallint",
570
571 /*
572 * Note: currently there's no value in offering the following multiword
573 * type names, because tab completion cannot succeed for them: we can't
574 * disambiguate until somewhere in the second word, at which point we
575 * won't have the first word as context. ("double precision" does work,
576 * as long as no other type name begins with "double".) Leave them out to
577 * encourage users to use the PG-specific aliases, which we can complete.
578 */
579#ifdef NOT_USED
580 "bit varying",
581 "character varying",
582 "time with time zone",
583 "time without time zone",
584 "timestamp with time zone",
585 "timestamp without time zone",
586#endif
587 NULL
588};
589
591 .catname = "pg_catalog.pg_type t",
592 /* selcondition --- ignore table rowtypes and array types */
593 .selcondition = "(t.typrelid = 0 "
594 " OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
595 " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
596 "AND t.typname !~ '^_'",
597 .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
598 .namespace = "t.typnamespace",
599 .result = "t.typname",
601};
602
604 .catname = "pg_catalog.pg_type t",
605 /* selcondition --- only get composite types */
606 .selcondition = "(SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
607 " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) "
608 "AND t.typname !~ '^_'",
609 .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
610 .namespace = "t.typnamespace",
611 .result = "t.typname",
612};
613
615 .catname = "pg_catalog.pg_type t",
616 .selcondition = "t.typtype = 'd'",
617 .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
618 .namespace = "t.typnamespace",
619 .result = "t.typname",
620};
621
623 .catname = "pg_catalog.pg_enum e, pg_catalog.pg_type t",
624 .selcondition = "t.oid = e.enumtypid",
625 .result = "pg_catalog.quote_literal(enumlabel)",
626 .refname = "t.typname",
627 .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
628 .refnamespace = "t.typnamespace",
629};
630
632 .catname = "pg_catalog.pg_enum e, pg_catalog.pg_type t",
633 .selcondition = "t.oid = e.enumtypid",
634 .result = "e.enumlabel",
635 .refname = "t.typname",
636 .refviscondition = "pg_catalog.pg_type_is_visible(t.oid)",
637 .refnamespace = "t.typnamespace",
638};
639
640/* Note: this intentionally accepts aggregates as well as plain functions */
642 {
643 .min_server_version = 110000,
644 .catname = "pg_catalog.pg_proc p",
645 .selcondition = "p.prokind != 'p'",
646 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
647 .namespace = "p.pronamespace",
648 .result = "p.proname",
649 },
650 {
651 .catname = "pg_catalog.pg_proc p",
652 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
653 .namespace = "p.pronamespace",
654 .result = "p.proname",
655 }
656};
657
659 {
660 .min_server_version = 110000,
661 .catname = "pg_catalog.pg_proc p",
662 .selcondition = "p.prokind = 'p'",
663 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
664 .namespace = "p.pronamespace",
665 .result = "p.proname",
666 },
667 {
668 /* not supported in older versions */
669 .catname = NULL,
670 }
671};
672
674 .catname = "pg_catalog.pg_proc p",
675 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
676 .namespace = "p.pronamespace",
677 .result = "p.proname",
678};
679
681 .catname = "pg_catalog.pg_class c",
682 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
683 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
684 .namespace = "c.relnamespace",
685 .result = "c.relname",
686};
687
689 .catname = "pg_catalog.pg_class c",
690 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
691 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
692 .namespace = "c.relnamespace",
693 .result = "c.relname",
694};
695
697 .catname = "pg_catalog.pg_class c",
698 .selcondition =
699 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
701 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
702 .namespace = "c.relnamespace",
703 .result = "c.relname",
704};
705
707 .catname = "pg_catalog.pg_class c",
708 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
709 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
710 .namespace = "c.relnamespace",
711 .result = "c.relname",
712};
713
715 .catname = "pg_catalog.pg_class c, pg_catalog.pg_constraint con",
716 .selcondition = "c.oid=con.conrelid and c.relkind IN ("
719 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
720 .namespace = "c.relnamespace",
721 .result = "c.relname",
722 .use_distinct = true,
723 .refname = "con.conname",
724};
725
727 .catname = "pg_catalog.pg_class c, pg_catalog.pg_policy p",
728 .selcondition = "c.oid=p.polrelid",
729 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
730 .namespace = "c.relnamespace",
731 .result = "c.relname",
732 .use_distinct = true,
733 .refname = "p.polname",
734};
735
737 .catname = "pg_catalog.pg_class c, pg_catalog.pg_rewrite r",
738 .selcondition = "c.oid=r.ev_class",
739 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
740 .namespace = "c.relnamespace",
741 .result = "c.relname",
742 .use_distinct = true,
743 .refname = "r.rulename",
744};
745
747 .catname = "pg_catalog.pg_class c, pg_catalog.pg_trigger t",
748 .selcondition = "c.oid=t.tgrelid",
749 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
750 .namespace = "c.relnamespace",
751 .result = "c.relname",
752 .use_distinct = true,
753 .refname = "t.tgname",
754};
755
757 .catname = "pg_catalog.pg_ts_config c",
758 .viscondition = "pg_catalog.pg_ts_config_is_visible(c.oid)",
759 .namespace = "c.cfgnamespace",
760 .result = "c.cfgname",
761};
762
764 .catname = "pg_catalog.pg_ts_dict d",
765 .viscondition = "pg_catalog.pg_ts_dict_is_visible(d.oid)",
766 .namespace = "d.dictnamespace",
767 .result = "d.dictname",
768};
769
771 .catname = "pg_catalog.pg_ts_parser p",
772 .viscondition = "pg_catalog.pg_ts_parser_is_visible(p.oid)",
773 .namespace = "p.prsnamespace",
774 .result = "p.prsname",
775};
776
778 .catname = "pg_catalog.pg_ts_template t",
779 .viscondition = "pg_catalog.pg_ts_template_is_visible(t.oid)",
780 .namespace = "t.tmplnamespace",
781 .result = "t.tmplname",
782};
783
785 .catname = "pg_catalog.pg_class c",
786 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
787 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
788 .namespace = "c.relnamespace",
789 .result = "c.relname",
790};
791
793 .catname = "pg_catalog.pg_class c",
794 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
795 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
796 .namespace = "c.relnamespace",
797 .result = "c.relname",
798};
799
801 .catname = "pg_catalog.pg_class c",
802 .selcondition =
803 "c.relkind IN (" CppAsString2(RELKIND_INDEX) ", "
805 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
806 .namespace = "c.relnamespace",
807 .result = "c.relname",
808};
809
811 .catname = "pg_catalog.pg_class c",
812 .selcondition = "c.relkind = " CppAsString2(RELKIND_PARTITIONED_INDEX),
813 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
814 .namespace = "c.relnamespace",
815 .result = "c.relname",
816};
817
819 .catname = "pg_catalog.pg_class c",
820 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PROPGRAPH) ")",
821 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
822 .namespace = "c.relnamespace",
823 .result = "pg_catalog.quote_ident(c.relname)",
824};
825
826
827/* All relations */
829 .catname = "pg_catalog.pg_class c",
830 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
831 .namespace = "c.relnamespace",
832 .result = "c.relname",
833};
834
835/* partitioned relations */
837 .catname = "pg_catalog.pg_class c",
838 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE)
840 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
841 .namespace = "c.relnamespace",
842 .result = "c.relname",
843};
844
846 .catname = "pg_catalog.pg_opfamily c",
847 .viscondition = "pg_catalog.pg_opfamily_is_visible(c.oid)",
848 .namespace = "c.opfnamespace",
849 .result = "c.opfname",
850};
851
852/* Relations supporting INSERT, UPDATE or DELETE */
854 .catname = "pg_catalog.pg_class c",
855 .selcondition =
856 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
860 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
861 .namespace = "c.relnamespace",
862 .result = "c.relname",
863};
864
865/* Relations supporting MERGE */
867 .catname = "pg_catalog.pg_class c",
868 .selcondition =
869 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
872 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
873 .namespace = "c.relnamespace",
874 .result = "c.relname",
875};
876
877/* Relations supporting SELECT */
879 .catname = "pg_catalog.pg_class c",
880 .selcondition =
881 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
887 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
888 .namespace = "c.relnamespace",
889 .result = "c.relname",
890};
891
892/* Relations supporting TRUNCATE */
894 .catname = "pg_catalog.pg_class c",
895 .selcondition =
896 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
899 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
900 .namespace = "c.relnamespace",
901 .result = "c.relname",
902};
903
904/* Relations supporting GRANT are currently same as those supporting SELECT */
905#define Query_for_list_of_grantables Query_for_list_of_selectables
906
907/* Relations supporting ANALYZE */
909 .catname = "pg_catalog.pg_class c",
910 .selcondition =
911 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
915 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
916 .namespace = "c.relnamespace",
917 .result = "c.relname",
918};
919
920/*
921 * Relations supporting COPY TO/FROM are currently almost the same as
922 * those supporting ANALYZE. Although views with INSTEAD OF INSERT triggers
923 * can be used with COPY FROM, they are rarely used for this purpose,
924 * so plain views are intentionally excluded from this tab completion.
925 */
926#define Query_for_list_of_tables_for_copy Query_for_list_of_analyzables
927
928/* Relations supporting index creation */
930 .catname = "pg_catalog.pg_class c",
931 .selcondition =
932 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
935 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
936 .namespace = "c.relnamespace",
937 .result = "c.relname",
938};
939
940/*
941 * Relations supporting VACUUM are currently same as those supporting
942 * indexing.
943 */
944#define Query_for_list_of_vacuumables Query_for_list_of_indexables
945
946/* Relations supporting CLUSTER */
948 .catname = "pg_catalog.pg_class c",
949 .selcondition =
950 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
953 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
954 .namespace = "c.relnamespace",
955 .result = "c.relname",
956};
957
959 .catname = "pg_catalog.pg_constraint c",
960 .selcondition = "c.conrelid <> 0",
961 .namespace = "c.connamespace",
962 .result = "c.conname",
963};
964
966 .catname = "pg_catalog.pg_statistic_ext s",
967 .viscondition = "pg_catalog.pg_statistics_obj_is_visible(s.oid)",
968 .namespace = "s.stxnamespace",
969 .result = "s.stxname",
970};
971
973 .catname = "pg_catalog.pg_collation c",
974 .selcondition = "c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))",
975 .viscondition = "pg_catalog.pg_collation_is_visible(c.oid)",
976 .namespace = "c.collnamespace",
977 .result = "c.collname",
978};
979
981 .catname = "pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i",
982 .selcondition = "c1.oid=i.inhparent and i.inhrelid=c2.oid and c2.relispartition",
983 .viscondition = "pg_catalog.pg_table_is_visible(c2.oid)",
984 .namespace = "c2.relnamespace",
985 .result = "c2.relname",
986 .refname = "c1.relname",
987 .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
988 .refnamespace = "c1.relnamespace",
989};
990
992 .catname = "pg_catalog.pg_rewrite r, pg_catalog.pg_class c1",
993 .selcondition = "r.ev_class=c1.oid",
994 .result = "r.rulename",
995 .refname = "c1.relname",
996 .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
997 .refnamespace = "c1.relnamespace",
998};
999
1001 .catname = "pg_catalog.pg_trigger t, pg_catalog.pg_class c1",
1002 .selcondition = "t.tgrelid=c1.oid and not t.tgisinternal",
1003 .result = "t.tgname",
1004 .refname = "c1.relname",
1005 .refviscondition = "pg_catalog.pg_table_is_visible(c1.oid)",
1006 .refnamespace = "c1.relnamespace",
1007};
1008
1009
1010/*
1011 * Queries to get lists of names of various kinds of things, possibly
1012 * restricted to names matching a partially entered name. Don't use
1013 * this method where the user might wish to enter a schema-qualified
1014 * name; make a SchemaQuery instead.
1015 *
1016 * In these queries, there must be a restriction clause of the form
1017 * output LIKE '%s'
1018 * where "output" is the same string that the query returns. The %s
1019 * will be replaced by a LIKE pattern to match the already-typed text.
1020 *
1021 * There can be a second '%s', which will be replaced by a suitably-escaped
1022 * version of the string provided in completion_ref_object. If there is a
1023 * third '%s', it will be replaced by a suitably-escaped version of the string
1024 * provided in completion_ref_schema. NOTE: using completion_ref_object
1025 * that way is usually the wrong thing, and using completion_ref_schema
1026 * that way is always the wrong thing. Make a SchemaQuery instead.
1027 */
1028
1029#define Query_for_list_of_template_databases \
1030"SELECT d.datname "\
1031" FROM pg_catalog.pg_database d "\
1032" WHERE d.datname LIKE '%s' "\
1033" AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
1034
1035#define Query_for_list_of_databases \
1036"SELECT datname FROM pg_catalog.pg_database "\
1037" WHERE datname LIKE '%s'"
1038
1039#define Query_for_list_of_database_vars \
1040"SELECT conf FROM ("\
1041" SELECT setdatabase, pg_catalog.split_part(pg_catalog.unnest(setconfig),'=',1) conf"\
1042" FROM pg_db_role_setting "\
1043" ) s, pg_database d "\
1044" WHERE s.setdatabase = d.oid "\
1045" AND conf LIKE '%s'"\
1046" AND d.datname LIKE '%s'"
1047
1048#define Query_for_list_of_tablespaces \
1049"SELECT spcname FROM pg_catalog.pg_tablespace "\
1050" WHERE spcname LIKE '%s'"
1051
1052#define Query_for_list_of_encodings \
1053" SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
1054" FROM pg_catalog.pg_conversion "\
1055" WHERE pg_catalog.pg_encoding_to_char(conforencoding) LIKE pg_catalog.upper('%s')"
1056
1057#define Query_for_list_of_languages \
1058"SELECT lanname "\
1059" FROM pg_catalog.pg_language "\
1060" WHERE lanname != 'internal' "\
1061" AND lanname LIKE '%s'"
1062
1063#define Query_for_list_of_schemas \
1064"SELECT nspname FROM pg_catalog.pg_namespace "\
1065" WHERE nspname LIKE '%s'"
1066
1067/* Use COMPLETE_WITH_QUERY_VERBATIM with these queries for GUC names: */
1068#define Query_for_list_of_alter_system_set_vars \
1069"SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
1070" WHERE context != 'internal' "\
1071" AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1072
1073#define Query_for_list_of_set_vars \
1074"SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
1075" WHERE context IN ('user', 'superuser') "\
1076" AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1077
1078#define Query_for_list_of_show_vars \
1079"SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\
1080" WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1081
1082#define Query_for_list_of_roles \
1083" SELECT rolname "\
1084" FROM pg_catalog.pg_roles "\
1085" WHERE rolname LIKE '%s'"
1086
1087/* add these to Query_for_list_of_roles in OWNER contexts */
1088#define Keywords_for_list_of_owner_roles \
1089"CURRENT_ROLE", "CURRENT_USER", "SESSION_USER"
1090
1091/* add these to Query_for_list_of_roles in GRANT contexts */
1092#define Keywords_for_list_of_grant_roles \
1093Keywords_for_list_of_owner_roles, "PUBLIC"
1094
1095#define Query_for_all_table_constraints \
1096"SELECT conname "\
1097" FROM pg_catalog.pg_constraint c "\
1098" WHERE c.conrelid <> 0 "\
1099" and conname LIKE '%s'"
1100
1101#define Query_for_list_of_fdws \
1102" SELECT fdwname "\
1103" FROM pg_catalog.pg_foreign_data_wrapper "\
1104" WHERE fdwname LIKE '%s'"
1105
1106#define Query_for_list_of_servers \
1107" SELECT srvname "\
1108" FROM pg_catalog.pg_foreign_server "\
1109" WHERE srvname LIKE '%s'"
1110
1111#define Query_for_list_of_user_mappings \
1112" SELECT usename "\
1113" FROM pg_catalog.pg_user_mappings "\
1114" WHERE usename LIKE '%s'"
1115
1116#define Query_for_list_of_user_vars \
1117"SELECT conf FROM ("\
1118" SELECT rolname, pg_catalog.split_part(pg_catalog.unnest(rolconfig),'=',1) conf"\
1119" FROM pg_catalog.pg_roles"\
1120" ) s"\
1121" WHERE s.conf like '%s' "\
1122" AND s.rolname LIKE '%s'"
1123
1124#define Query_for_list_of_access_methods \
1125" SELECT amname "\
1126" FROM pg_catalog.pg_am "\
1127" WHERE amname LIKE '%s'"
1128
1129#define Query_for_list_of_index_access_methods \
1130" SELECT amname "\
1131" FROM pg_catalog.pg_am "\
1132" WHERE amname LIKE '%s' AND "\
1133" amtype=" CppAsString2(AMTYPE_INDEX)
1134
1135#define Query_for_list_of_table_access_methods \
1136" SELECT amname "\
1137" FROM pg_catalog.pg_am "\
1138" WHERE amname LIKE '%s' AND "\
1139" amtype=" CppAsString2(AMTYPE_TABLE)
1140
1141#define Query_for_list_of_extensions \
1142" SELECT extname "\
1143" FROM pg_catalog.pg_extension "\
1144" WHERE extname LIKE '%s'"
1145
1146#define Query_for_list_of_available_extensions \
1147" SELECT name "\
1148" FROM pg_catalog.pg_available_extensions "\
1149" WHERE name LIKE '%s' AND installed_version IS NULL"
1150
1151#define Query_for_list_of_available_extension_versions \
1152" SELECT version "\
1153" FROM pg_catalog.pg_available_extension_versions "\
1154" WHERE version LIKE '%s' AND name='%s'"
1155
1156#define Query_for_list_of_prepared_statements \
1157" SELECT name "\
1158" FROM pg_catalog.pg_prepared_statements "\
1159" WHERE name LIKE '%s'"
1160
1161#define Query_for_list_of_event_triggers \
1162" SELECT evtname "\
1163" FROM pg_catalog.pg_event_trigger "\
1164" WHERE evtname LIKE '%s'"
1165
1166#define Query_for_list_of_tablesample_methods \
1167" SELECT proname "\
1168" FROM pg_catalog.pg_proc "\
1169" WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
1170" proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
1171" proname LIKE '%s'"
1172
1173#define Query_for_list_of_policies \
1174" SELECT polname "\
1175" FROM pg_catalog.pg_policy "\
1176" WHERE polname LIKE '%s'"
1177
1178#define Query_for_values_of_enum_GUC \
1179" SELECT val FROM ( "\
1180" SELECT name, pg_catalog.unnest(enumvals) AS val "\
1181" FROM pg_catalog.pg_settings "\
1182" ) ss "\
1183" WHERE val LIKE '%s'"\
1184" and pg_catalog.lower(name)=pg_catalog.lower('%s')"
1185
1186#define Query_for_list_of_channels \
1187" SELECT channel "\
1188" FROM pg_catalog.pg_listening_channels() AS channel "\
1189" WHERE channel LIKE '%s'"
1190
1191#define Query_for_list_of_cursors \
1192" SELECT name "\
1193" FROM pg_catalog.pg_cursors "\
1194" WHERE name LIKE '%s'"
1195
1196#define Query_for_list_of_timezone_names_unquoted \
1197" SELECT name "\
1198" FROM pg_catalog.pg_timezone_names() "\
1199" WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1200
1201#define Query_for_list_of_timezone_names_quoted_out \
1202"SELECT pg_catalog.quote_literal(name) AS name "\
1203" FROM pg_catalog.pg_timezone_names() "\
1204" WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
1205
1206#define Query_for_list_of_timezone_names_quoted_in \
1207"SELECT pg_catalog.quote_literal(name) AS name "\
1208" FROM pg_catalog.pg_timezone_names() "\
1209" WHERE pg_catalog.quote_literal(pg_catalog.lower(name)) LIKE pg_catalog.lower('%s')"
1210
1211/* Privilege options shared between GRANT and REVOKE */
1212#define Privilege_options_of_grant_and_revoke \
1213"SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER", \
1214"CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE", "SET", "ALTER SYSTEM", \
1215"MAINTAIN", "ALL"
1216
1217/* ALTER PROCEDURE options */
1218#define Alter_procedure_options \
1219"DEPENDS ON EXTENSION", "EXTERNAL SECURITY", "NO DEPENDS ON EXTENSION", \
1220"OWNER TO", "RENAME TO", "RESET", "SECURITY", "SET"
1221
1222/* ALTER ROUTINE options */
1223#define Alter_routine_options \
1224Alter_procedure_options, "COST", "IMMUTABLE", "LEAKPROOF", "NOT LEAKPROOF", \
1225"PARALLEL", "ROWS", "STABLE", "VOLATILE"
1226
1227/* ALTER FUNCTION options */
1228#define Alter_function_options \
1229Alter_routine_options, "CALLED ON NULL INPUT", "RETURNS NULL ON NULL INPUT", \
1230"STRICT", "SUPPORT"
1231
1232/* COPY options shared between FROM and TO */
1233#define Copy_common_options \
1234"DELIMITER", "ENCODING", "ESCAPE", "FORMAT", "HEADER", "NULL", "QUOTE"
1235
1236/* COPY FROM options */
1237#define Copy_from_options \
1238Copy_common_options, "DEFAULT", "FORCE_NOT_NULL", "FORCE_NULL", "FREEZE", \
1239"LOG_VERBOSITY", "ON_ERROR", "REJECT_LIMIT"
1240
1241/* COPY TO options */
1242#define Copy_to_options \
1243Copy_common_options, "FORCE_QUOTE", "FORCE_ARRAY"
1244
1245/*
1246 * These object types were introduced later than our support cutoff of
1247 * server version 9.2. We use the VersionedQuery infrastructure so that
1248 * we don't send certain-to-fail queries to older servers.
1249 */
1250
1252 {100000,
1253 " SELECT pubname "
1254 " FROM pg_catalog.pg_publication "
1255 " WHERE pubname LIKE '%s'"
1256 },
1257 {0, NULL}
1258};
1259
1261 {100000,
1262 " SELECT s.subname "
1263 " FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "
1264 " WHERE s.subname LIKE '%s' "
1265 " AND d.datname = pg_catalog.current_database() "
1266 " AND s.subdbid = d.oid"
1267 },
1268 {0, NULL}
1269};
1270
1271 /* Known command-starting keywords. */
1272static const char *const sql_commands[] = {
1273 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CALL", "CHECKPOINT", "CLOSE", "CLUSTER",
1274 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1275 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1276 "FETCH", "GRANT", "IMPORT FOREIGN SCHEMA", "INSERT INTO", "LISTEN", "LOAD", "LOCK",
1277 "MERGE INTO", "MOVE", "NOTIFY", "PREPARE",
1278 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE", "REPACK",
1279 "RESET", "REVOKE", "ROLLBACK",
1280 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1281 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES",
1282 "WAIT FOR", "WITH",
1283 NULL
1284};
1285
1286/*
1287 * This is a list of all "things" in Pgsql, which can show up after CREATE or
1288 * DROP; and there is also a query to get a list of them.
1289 */
1290
1291typedef struct
1292{
1293 const char *name;
1294 /* Provide at most one of these three types of query: */
1295 const char *query; /* simple query, or NULL */
1296 const VersionedQuery *vquery; /* versioned query, or NULL */
1297 const SchemaQuery *squery; /* schema query, or NULL */
1298 const char *const *keywords; /* keywords to be offered as well */
1299 const uint32 flags; /* visibility flags, see below */
1301
1302#define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
1303#define THING_NO_DROP (1 << 1) /* should not show up after DROP */
1304#define THING_NO_ALTER (1 << 2) /* should not show up after ALTER */
1305#define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
1306
1307/* When we have DROP USER etc, also offer MAPPING FOR */
1308static const char *const Keywords_for_user_thing[] = {
1309 "MAPPING FOR",
1310 NULL
1311};
1312
1313static const pgsql_thing_t words_after_create[] = {
1314 {"ACCESS METHOD", NULL, NULL, NULL, NULL, THING_NO_ALTER},
1315 {"AGGREGATE", NULL, NULL, Query_for_list_of_aggregates},
1316 {"CAST", NULL, NULL, NULL}, /* Casts have complex structures for names, so
1317 * skip it */
1318 {"COLLATION", NULL, NULL, &Query_for_list_of_collations},
1319
1320 /*
1321 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
1322 * to be used only by pg_dump.
1323 */
1325 {"CONVERSION", "SELECT conname FROM pg_catalog.pg_conversion WHERE conname LIKE '%s'"},
1326 {"DATABASE", Query_for_list_of_databases},
1327 {"DEFAULT PRIVILEGES", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1329 {"DOMAIN", NULL, NULL, &Query_for_list_of_domains},
1330 {"EVENT TRIGGER", NULL, NULL, NULL},
1331 {"EXTENSION", Query_for_list_of_extensions},
1332 {"FOREIGN DATA WRAPPER", NULL, NULL, NULL},
1333 {"FOREIGN TABLE", NULL, NULL, NULL},
1334 {"FUNCTION", NULL, NULL, Query_for_list_of_functions},
1335 {"GROUP", Query_for_list_of_roles},
1336 {"INDEX", NULL, NULL, &Query_for_list_of_indexes},
1337 {"LANGUAGE", Query_for_list_of_languages},
1338 {"LARGE OBJECT", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1339 {"MATERIALIZED VIEW", NULL, NULL, &Query_for_list_of_matviews},
1340 {"OPERATOR", NULL, NULL, NULL}, /* Querying for this is probably not such
1341 * a good idea. */
1342 {"OR REPLACE", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER},
1343 {"OWNED", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_ALTER}, /* for DROP OWNED BY ... */
1345 {"POLICY", NULL, NULL, NULL},
1346 {"PROCEDURE", NULL, NULL, Query_for_list_of_procedures},
1347 {"PROPERTY GRAPH", NULL, NULL, &Query_for_list_of_propgraphs},
1348 {"PUBLICATION", NULL, Query_for_list_of_publications},
1349 {"ROLE", Query_for_list_of_roles},
1351 {"RULE", "SELECT rulename FROM pg_catalog.pg_rules WHERE rulename LIKE '%s'"},
1352 {"SCHEMA", Query_for_list_of_schemas},
1353 {"SEQUENCE", NULL, NULL, &Query_for_list_of_sequences},
1354 {"SERVER", Query_for_list_of_servers},
1355 {"STATISTICS", NULL, NULL, &Query_for_list_of_statistics},
1356 {"SUBSCRIPTION", NULL, Query_for_list_of_subscriptions},
1357 {"SYSTEM", NULL, NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1358 {"TABLE", NULL, NULL, &Query_for_list_of_tables},
1359 {"TABLESPACE", Query_for_list_of_tablespaces},
1360 {"TEMP", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE
1361 * ... */
1363 {"TEMPORARY", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMPORARY
1364 * TABLE ... */
1365 {"TEXT SEARCH", NULL, NULL, NULL},
1366 {"TRANSFORM", NULL, NULL, NULL, NULL, THING_NO_ALTER},
1367 {"TRIGGER", "SELECT tgname FROM pg_catalog.pg_trigger WHERE tgname LIKE '%s' AND NOT tgisinternal"},
1369 {"UNIQUE", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNIQUE
1370 * INDEX ... */
1371 {"UNLOGGED", NULL, NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNLOGGED
1372 * TABLE ... */
1374 {"USER MAPPING FOR", NULL, NULL, NULL},
1375 {"VIEW", NULL, NULL, &Query_for_list_of_views},
1376 {NULL} /* end of list */
1377};
1378
1379/*
1380 * The tcpatterns[] table provides the initial pattern-match rule for each
1381 * switch case in match_previous_words(). The contents of the table
1382 * are constructed by gen_tabcomplete.pl.
1383 */
1384
1385/* Basic match rules appearing in tcpatterns[].kind */
1386enum TCPatternKind
1387{
1388 Match,
1389 MatchCS,
1390 HeadMatch,
1392 TailMatch,
1394};
1395
1396/* Things besides string literals that can appear in tcpatterns[].words */
1397#define MatchAny NULL
1398#define MatchAnyExcept(pattern) ("!" pattern)
1399#define MatchAnyN ""
1400
1401/* One entry in tcpatterns[] */
1402typedef struct
1403{
1404 int id; /* case label used in match_previous_words */
1405 enum TCPatternKind kind; /* match kind, see above */
1406 int nwords; /* length of words[] array */
1407 const char *const *words; /* array of match words */
1408} TCPattern;
1409
1410/* Macro emitted by gen_tabcomplete.pl to fill a tcpatterns[] entry */
1411#define TCPAT(id, kind, ...) \
1412 { (id), (kind), VA_ARGS_NARGS(__VA_ARGS__), \
1413 (const char * const []) { __VA_ARGS__ } }
1414
1415#ifdef SWITCH_CONVERSION_APPLIED
1416
1417static const TCPattern tcpatterns[] =
1418{
1419 /* Insert tab-completion pattern data here. */
1420};
1421
1422#endif /* SWITCH_CONVERSION_APPLIED */
1423
1424/* Storage parameters for CREATE TABLE and ALTER TABLE */
1425static const char *const table_storage_parameters[] = {
1426 "autovacuum_analyze_scale_factor",
1427 "autovacuum_analyze_threshold",
1428 "autovacuum_enabled",
1429 "autovacuum_freeze_max_age",
1430 "autovacuum_freeze_min_age",
1431 "autovacuum_freeze_table_age",
1432 "autovacuum_multixact_freeze_max_age",
1433 "autovacuum_multixact_freeze_min_age",
1434 "autovacuum_multixact_freeze_table_age",
1435 "autovacuum_vacuum_cost_delay",
1436 "autovacuum_vacuum_cost_limit",
1437 "autovacuum_vacuum_insert_scale_factor",
1438 "autovacuum_vacuum_insert_threshold",
1439 "autovacuum_vacuum_max_threshold",
1440 "autovacuum_vacuum_scale_factor",
1441 "autovacuum_vacuum_threshold",
1442 "fillfactor",
1443 "log_autovacuum_min_duration",
1444 "log_autoanalyze_min_duration",
1445 "parallel_workers",
1446 "toast.autovacuum_enabled",
1447 "toast.autovacuum_freeze_max_age",
1448 "toast.autovacuum_freeze_min_age",
1449 "toast.autovacuum_freeze_table_age",
1450 "toast.autovacuum_multixact_freeze_max_age",
1451 "toast.autovacuum_multixact_freeze_min_age",
1452 "toast.autovacuum_multixact_freeze_table_age",
1453 "toast.autovacuum_vacuum_cost_delay",
1454 "toast.autovacuum_vacuum_cost_limit",
1455 "toast.autovacuum_vacuum_insert_scale_factor",
1456 "toast.autovacuum_vacuum_insert_threshold",
1457 "toast.autovacuum_vacuum_max_threshold",
1458 "toast.autovacuum_vacuum_scale_factor",
1459 "toast.autovacuum_vacuum_threshold",
1460 "toast.log_autovacuum_min_duration",
1461 "toast.vacuum_index_cleanup",
1462 "toast.vacuum_max_eager_freeze_failure_rate",
1463 "toast.vacuum_truncate",
1464 "toast_tuple_target",
1465 "user_catalog_table",
1466 "vacuum_index_cleanup",
1467 "vacuum_max_eager_freeze_failure_rate",
1468 "vacuum_truncate",
1469 NULL
1470};
1471
1472/* Optional parameters for CREATE VIEW and ALTER VIEW */
1473static const char *const view_optional_parameters[] = {
1474 "check_option",
1475 "security_barrier",
1476 "security_invoker",
1477 NULL
1478};
1479
1480/* Forward declaration of functions */
1481static char **psql_completion(const char *text, int start, int end);
1482static char **match_previous_words(int pattern_id,
1483 const char *text, int start, int end,
1484 char **previous_words,
1486static char *create_command_generator(const char *text, int state);
1487static char *drop_command_generator(const char *text, int state);
1488static char *alter_command_generator(const char *text, int state);
1489static char *complete_from_query(const char *text, int state);
1490static char *complete_from_versioned_query(const char *text, int state);
1491static char *complete_from_schema_query(const char *text, int state);
1492static char *complete_from_versioned_schema_query(const char *text, int state);
1493static char *_complete_from_query(const char *simple_query,
1495 const char *const *keywords,
1496 bool verbatim,
1497 const char *text, int state);
1498static void set_completion_reference(const char *word);
1499static void set_completion_reference_verbatim(const char *word);
1500static char *complete_from_list(const char *text, int state);
1501static char *complete_from_const(const char *text, int state);
1502static void append_variable_names(char ***varnames, int *nvars,
1503 int *maxvars, const char *varname,
1504 const char *prefix, const char *suffix);
1505static char **complete_from_variables(const char *text,
1506 const char *prefix, const char *suffix, bool need_value);
1507static char *complete_from_files(const char *text, int state);
1508static char *_complete_from_files(const char *text, int state);
1509
1510static char *pg_strdup_keyword_case(const char *s, const char *ref);
1511static char *escape_string(const char *text);
1512static char *make_like_pattern(const char *word);
1513static void parse_identifier(const char *ident,
1514 char **schemaname, char **objectname,
1515 bool *schemaquoted, bool *objectquoted);
1516static char *requote_identifier(const char *schemaname, const char *objectname,
1517 bool quote_schema, bool quote_object);
1518static bool identifier_needs_quotes(const char *ident);
1519static PGresult *exec_query(const char *query);
1520
1521static char **get_previous_words(int point, char **buffer, int *nwords);
1522
1523static char *get_guctype(const char *varname);
1524
1525#ifdef USE_FILENAME_QUOTING_FUNCTIONS
1526static char *quote_file_name(char *fname, int match_type, char *quote_pointer);
1527static char *dequote_file_name(char *fname, int quote_char);
1528#endif
1529
1530
1531/*
1532 * Initialize the readline library for our purposes.
1533 */
1534void
1536{
1537 rl_readline_name = (char *) pset.progname;
1539
1540#ifdef USE_FILENAME_QUOTING_FUNCTIONS
1543#endif
1544
1546
1547 /*
1548 * Ideally we'd include '"' in rl_completer_quote_characters too, which
1549 * should allow us to complete quoted identifiers that include spaces.
1550 * However, the library support for rl_completer_quote_characters is
1551 * presently too inconsistent to want to mess with that. (Note in
1552 * particular that libedit has this variable but completely ignores it.)
1553 */
1555
1556 /*
1557 * Set rl_filename_quote_characters to "all possible characters",
1558 * otherwise Readline will skip filename quoting if it thinks a filename
1559 * doesn't need quoting. Readline actually interprets this as bytes, so
1560 * there are no encoding considerations here.
1561 */
1562#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1563 {
1564 unsigned char *fqc = (unsigned char *) pg_malloc(256);
1565
1566 for (int i = 0; i < 255; i++)
1567 fqc[i] = (unsigned char) (i + 1);
1568 fqc[255] = '\0';
1569 rl_filename_quote_characters = (const char *) fqc;
1570 }
1571#endif
1572
1574
1575 /*
1576 * There is a variable rl_completion_query_items for this but apparently
1577 * it's not defined everywhere.
1578 */
1579}
1580
1581/*
1582 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1583 * using case-insensitive or case-sensitive comparisons.
1584 *
1585 * If pattern is NULL, it's a wild card that matches any word.
1586 * If pattern begins with '!', the result is negated, ie we check that 'word'
1587 * does *not* match any alternative appearing in the rest of 'pattern'.
1588 * Any alternative can contain '*' which is a wild card, i.e., it can match
1589 * any substring; however, we allow at most one '*' per alternative.
1590 *
1591 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1592 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1593 * just be written directly in patterns.) There is also MatchAnyN, but that
1594 * is supported only in Matches/MatchesCS and is not handled here.
1595 */
1596static bool
1597word_matches(const char *pattern,
1598 const char *word,
1599 bool case_sensitive)
1600{
1601 size_t wordlen;
1602
1603#define cimatch(s1, s2, n) \
1604 (case_sensitive ? strncmp(s1, s2, n) == 0 : pg_strncasecmp(s1, s2, n) == 0)
1605
1606 /* NULL pattern matches anything. */
1607 if (pattern == NULL)
1608 return true;
1609
1610 /* Handle negated patterns from the MatchAnyExcept macro. */
1611 if (*pattern == '!')
1612 return !word_matches(pattern + 1, word, case_sensitive);
1613
1614 /* Else consider each alternative in the pattern. */
1615 wordlen = strlen(word);
1616 for (;;)
1617 {
1618 const char *star = NULL;
1619 const char *c;
1620
1621 /* Find end of current alternative, and locate any wild card. */
1622 c = pattern;
1623 while (*c != '\0' && *c != '|')
1624 {
1625 if (*c == '*')
1626 star = c;
1627 c++;
1628 }
1629 /* Was there a wild card? */
1630 if (star)
1631 {
1632 /* Yes, wildcard match? */
1633 size_t beforelen = star - pattern,
1634 afterlen = c - star - 1;
1635
1636 if (wordlen >= (beforelen + afterlen) &&
1637 cimatch(word, pattern, beforelen) &&
1638 cimatch(word + wordlen - afterlen, star + 1, afterlen))
1639 return true;
1640 }
1641 else
1642 {
1643 /* No, plain match? */
1644 if (wordlen == (c - pattern) &&
1645 cimatch(word, pattern, wordlen))
1646 return true;
1647 }
1648 /* Out of alternatives? */
1649 if (*c == '\0')
1650 break;
1651 /* Nope, try next alternative. */
1652 pattern = c + 1;
1653 }
1654
1655 return false;
1656}
1657
1658/*
1659 * Implementation of TailMatches and TailMatchesCS tests: do the last N words
1660 * in previous_words match the pattern arguments?
1661 *
1662 * The array indexing might look backwards, but remember that
1663 * previous_words[0] contains the *last* word on the line, not the first.
1664 */
1665static bool
1666TailMatchesArray(bool case_sensitive,
1668 int narg, const char *const *args)
1669{
1671 return false;
1672
1673 for (int argno = 0; argno < narg; argno++)
1674 {
1675 const char *arg = args[argno];
1676
1678 case_sensitive))
1679 return false;
1680 }
1681
1682 return true;
1683}
1684
1685/*
1686 * As above, but the pattern is passed as a variadic argument list.
1687 */
1688static bool
1689TailMatchesImpl(bool case_sensitive,
1691 int narg,...)
1692{
1693 const char *argarray[64];
1694 va_list args;
1695
1697
1699 return false;
1700
1701 va_start(args, narg);
1702 for (int argno = 0; argno < narg; argno++)
1703 argarray[argno] = va_arg(args, const char *);
1704 va_end(args);
1705
1706 return TailMatchesArray(case_sensitive,
1708 narg, argarray);
1709}
1710
1711/*
1712 * Implementation of HeadMatches and HeadMatchesCS tests: do the first N
1713 * words in previous_words match the pattern arguments?
1714 */
1715static bool
1716HeadMatchesArray(bool case_sensitive,
1718 int narg, const char *const *args)
1719{
1721 return false;
1722
1723 for (int argno = 0; argno < narg; argno++)
1724 {
1725 const char *arg = args[argno];
1726
1728 case_sensitive))
1729 return false;
1730 }
1731
1732 return true;
1733}
1734
1735/*
1736 * As above, but the pattern is passed as a variadic argument list.
1737 */
1738static bool
1739HeadMatchesImpl(bool case_sensitive,
1741 int narg,...)
1742{
1743 const char *argarray[64];
1744 va_list args;
1745
1747
1749 return false;
1750
1751 va_start(args, narg);
1752 for (int argno = 0; argno < narg; argno++)
1753 argarray[argno] = va_arg(args, const char *);
1754 va_end(args);
1755
1756 return HeadMatchesArray(case_sensitive,
1758 narg, argarray);
1759}
1760
1761/*
1762 * Implementation of Matches and MatchesCS tests: do all of the words
1763 * in previous_words match the pattern arguments?
1764 *
1765 * This supports an additional kind of wildcard: MatchAnyN (represented as "")
1766 * can match any number of words, including zero, in the middle of the list.
1767 */
1768static bool
1769MatchesArray(bool case_sensitive,
1771 int narg, const char *const *args)
1772{
1773 int match_any_pos = -1;
1774
1775 /* Even with MatchAnyN, there must be at least N-1 words */
1776 if (previous_words_count < narg - 1)
1777 return false;
1778
1779 /* Check for MatchAnyN */
1780 for (int argno = 0; argno < narg; argno++)
1781 {
1782 const char *arg = args[argno];
1783
1784 if (arg != NULL && arg[0] == '\0')
1785 {
1787 break;
1788 }
1789 }
1790
1791 if (match_any_pos < 0)
1792 {
1793 /* Standard case without MatchAnyN */
1795 return false;
1796
1797 /* Either Head or Tail match will do for the rest */
1798 if (!HeadMatchesArray(case_sensitive,
1800 narg, args))
1801 return false;
1802 }
1803 else
1804 {
1805 /* Match against head */
1806 if (!HeadMatchesArray(case_sensitive,
1808 match_any_pos, args))
1809 return false;
1810
1811 /* Match against tail */
1812 if (!TailMatchesArray(case_sensitive,
1814 narg - match_any_pos - 1,
1815 args + match_any_pos + 1))
1816 return false;
1817 }
1818
1819 return true;
1820}
1821
1822/*
1823 * As above, but the pattern is passed as a variadic argument list.
1824 */
1825static bool
1826MatchesImpl(bool case_sensitive,
1828 int narg,...)
1829{
1830 const char *argarray[64];
1831 va_list args;
1832
1834
1835 /* Even with MatchAnyN, there must be at least N-1 words */
1836 if (previous_words_count < narg - 1)
1837 return false;
1838
1839 va_start(args, narg);
1840 for (int argno = 0; argno < narg; argno++)
1841 argarray[argno] = va_arg(args, const char *);
1842 va_end(args);
1843
1844 return MatchesArray(case_sensitive,
1846 narg, argarray);
1847}
1848
1849/*
1850 * Check if the final character of 's' is 'c'.
1851 */
1852static bool
1853ends_with(const char *s, char c)
1854{
1855 size_t length = strlen(s);
1856
1857 return (length > 0 && s[length - 1] == c);
1858}
1859
1860/*
1861 * The completion function.
1862 *
1863 * According to readline spec this gets passed the text entered so far and its
1864 * start and end positions in the readline buffer. The return value is some
1865 * partially obscure list format that can be generated by readline's
1866 * rl_completion_matches() function, so we don't have to worry about it.
1867 */
1868static char **
1869psql_completion(const char *text, int start, int end)
1870{
1871 /* This is the variable we'll return. */
1872 char **matches = NULL;
1873
1874 /* Workspace for parsed words. */
1875 char *words_buffer;
1876
1877 /* This array will contain pointers to parsed words. */
1878 char **previous_words;
1879
1880 /* The number of words found on the input line. */
1882
1883 /*
1884 * For compactness, we use these macros to reference previous_words[].
1885 * Caution: do not access a previous_words[] entry without having checked
1886 * previous_words_count to be sure it's valid. In most cases below, that
1887 * check is implicit in a TailMatches() or similar macro, but in some
1888 * places we have to check it explicitly.
1889 */
1890#define prev_wd (previous_words[0])
1891#define prev2_wd (previous_words[1])
1892#define prev3_wd (previous_words[2])
1893#define prev4_wd (previous_words[3])
1894#define prev5_wd (previous_words[4])
1895#define prev6_wd (previous_words[5])
1896#define prev7_wd (previous_words[6])
1897#define prev8_wd (previous_words[7])
1898#define prev9_wd (previous_words[8])
1899
1900 /* Match the last N words before point, case-insensitively. */
1901#define TailMatches(...) \
1902 TailMatchesImpl(false, previous_words_count, previous_words, \
1903 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1904
1905 /* Match the last N words before point, case-sensitively. */
1906#define TailMatchesCS(...) \
1907 TailMatchesImpl(true, previous_words_count, previous_words, \
1908 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1909
1910 /* Match N words representing all of the line, case-insensitively. */
1911#define Matches(...) \
1912 MatchesImpl(false, previous_words_count, previous_words, \
1913 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1914
1915 /* Match N words representing all of the line, case-sensitively. */
1916#define MatchesCS(...) \
1917 MatchesImpl(true, previous_words_count, previous_words, \
1918 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1919
1920 /* Match the first N words on the line, case-insensitively. */
1921#define HeadMatches(...) \
1922 HeadMatchesImpl(false, previous_words_count, previous_words, \
1923 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1924
1925 /* Match the first N words on the line, case-sensitively. */
1926#define HeadMatchesCS(...) \
1927 HeadMatchesImpl(true, previous_words_count, previous_words, \
1928 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1929
1930 /* psql's backslash commands. */
1931 static const char *const backslash_commands[] = {
1932 "\\a",
1933 "\\bind", "\\bind_named",
1934 "\\connect", "\\conninfo", "\\C", "\\cd", "\\close_prepared", "\\copy",
1935 "\\copyright", "\\crosstabview",
1936 "\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp",
1937 "\\db", "\\dc", "\\dconfig", "\\dC", "\\dd", "\\ddp", "\\dD",
1938 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1939 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1940 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
1941 "\\drds", "\\drg", "\\dRs", "\\dRp", "\\ds",
1942 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dX", "\\dy",
1943 "\\echo", "\\edit", "\\ef", "\\elif", "\\else", "\\encoding",
1944 "\\endif", "\\endpipeline", "\\errverbose", "\\ev",
1945 "\\f", "\\flush", "\\flushrequest",
1946 "\\g", "\\gdesc", "\\getenv", "\\getresults", "\\gexec", "\\gset", "\\gx",
1947 "\\help", "\\html",
1948 "\\if", "\\include", "\\include_relative", "\\ir",
1949 "\\list", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1950 "\\out",
1951 "\\parse", "\\password", "\\print", "\\prompt", "\\pset",
1952 "\\qecho", "\\quit",
1953 "\\reset", "\\restrict",
1954 "\\s", "\\sendpipeline", "\\set", "\\setenv", "\\sf",
1955 "\\startpipeline", "\\sv", "\\syncpipeline",
1956 "\\t", "\\T", "\\timing",
1957 "\\unrestrict", "\\unset",
1958 "\\x",
1959 "\\warn", "\\watch", "\\write",
1960 "\\z",
1961 "\\!", "\\?",
1962 NULL
1963 };
1964
1965 /*
1966 * Temporary workaround for a bug in recent (2019) libedit: it incorrectly
1967 * de-escapes the input "text", causing us to fail to recognize backslash
1968 * commands. So get the string to look at from rl_line_buffer instead.
1969 */
1970 char *text_copy = pnstrdup(rl_line_buffer + start, end - start);
1971 text = text_copy;
1972
1973 /* Remember last char of the given input word. */
1974 completion_last_char = (end > start) ? text[end - start - 1] : '\0';
1975
1976 /* We usually want the append character to be a space. */
1978
1979 /* Clear a few things. */
1986
1987 /*
1988 * Scan the input line to extract the words before our current position.
1989 * According to those we'll make some smart decisions on what the user is
1990 * probably intending to type.
1991 */
1993 &words_buffer,
1995
1996 /* If current word is a backslash command, offer completions for that */
1997 if (text[0] == '\\')
1999
2000 /* If current word is a variable interpolation, handle that case */
2001 else if (text[0] == ':' && text[1] != ':')
2002 {
2003 if (text[1] == '\'')
2004 matches = complete_from_variables(text, ":'", "'", true);
2005 else if (text[1] == '"')
2006 matches = complete_from_variables(text, ":\"", "\"", true);
2007 else if (text[1] == '{' && text[2] == '?')
2008 matches = complete_from_variables(text, ":{?", "}", true);
2009 else
2010 matches = complete_from_variables(text, ":", "", true);
2011 }
2012
2013 /* If no previous word, suggest one of the basic sql commands */
2014 else if (previous_words_count == 0)
2016
2017 /* Else try completions based on matching patterns of previous words */
2018 else
2019 {
2020#ifdef SWITCH_CONVERSION_APPLIED
2021 /*
2022 * If we have transformed match_previous_words into a switch, iterate
2023 * through tcpatterns[] to see which pattern ids match.
2024 *
2025 * For now, we have to try the patterns in the order they are stored
2026 * (matching the order of switch cases in match_previous_words),
2027 * because some of the logic in match_previous_words assumes that
2028 * previous matches have been eliminated. This is fairly
2029 * unprincipled, and it is likely that there are undesirable as well
2030 * as desirable interactions hidden in the order of the pattern
2031 * checks. TODO: think about a better way to manage that.
2032 */
2033 for (int tindx = 0; tindx < lengthof(tcpatterns); tindx++)
2034 {
2035 const TCPattern *tcpat = tcpatterns + tindx;
2036 bool match = false;
2037
2038 switch (tcpat->kind)
2039 {
2040 case Match:
2041 match = MatchesArray(false,
2044 tcpat->nwords, tcpat->words);
2045 break;
2046 case MatchCS:
2047 match = MatchesArray(true,
2050 tcpat->nwords, tcpat->words);
2051 break;
2052 case HeadMatch:
2053 match = HeadMatchesArray(false,
2056 tcpat->nwords, tcpat->words);
2057 break;
2058 case HeadMatchCS:
2059 match = HeadMatchesArray(true,
2062 tcpat->nwords, tcpat->words);
2063 break;
2064 case TailMatch:
2065 match = TailMatchesArray(false,
2068 tcpat->nwords, tcpat->words);
2069 break;
2070 case TailMatchCS:
2071 match = TailMatchesArray(true,
2074 tcpat->nwords, tcpat->words);
2075 break;
2076 }
2077 if (match)
2078 {
2082 if (matches != NULL)
2083 break;
2084 }
2085 }
2086#else /* !SWITCH_CONVERSION_APPLIED */
2087 /*
2088 * If gen_tabcomplete.pl hasn't been applied to this code, just let
2089 * match_previous_words scan through all its patterns.
2090 */
2094#endif /* SWITCH_CONVERSION_APPLIED */
2095 }
2096
2097 /*
2098 * Finally, we look through the list of "things", such as TABLE, INDEX and
2099 * check if that was the previous word. If so, execute the query to get a
2100 * list of them.
2101 */
2102 if (matches == NULL && previous_words_count > 0)
2103 {
2104 const pgsql_thing_t *wac;
2105
2106 for (wac = words_after_create; wac->name != NULL; wac++)
2107 {
2108 if (pg_strcasecmp(prev_wd, wac->name) == 0)
2109 {
2110 if (wac->query)
2112 wac->keywords);
2113 else if (wac->vquery)
2115 wac->keywords);
2116 else if (wac->squery)
2118 wac->keywords);
2119 break;
2120 }
2121 }
2122 }
2123
2124 /*
2125 * If we still don't have anything to match we have to fabricate some sort
2126 * of default list. If we were to just return NULL, readline automatically
2127 * attempts filename completion, and that's usually no good.
2128 */
2129 if (matches == NULL)
2130 {
2131 COMPLETE_WITH_CONST(true, "");
2132 /* Also, prevent Readline from appending stuff to the non-match */
2134#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
2136#endif
2137 }
2138
2139 /* free storage */
2142 free(text_copy);
2147
2148 /* Return our Grand List O' Matches */
2149 return matches;
2150}
2151
2152/*
2153 * Subroutine to try matches based on previous_words.
2154 *
2155 * This can operate in one of two modes. As presented, the body of the
2156 * function is a long if-else-if chain that sequentially tries each known
2157 * match rule. That works, but some C compilers have trouble with such a long
2158 * else-if chain, either taking extra time to compile or failing altogether.
2159 * Therefore, we prefer to transform the else-if chain into a switch, and then
2160 * each call of this function considers just one match rule (under control of
2161 * a loop in psql_completion()). Compilers tend to be more ready to deal
2162 * with many-arm switches than many-arm else-if chains.
2163 *
2164 * Each if-condition in this function must begin with a call of one of the
2165 * functions Matches, HeadMatches, TailMatches, MatchesCS, HeadMatchesCS, or
2166 * TailMatchesCS. The preprocessor gen_tabcomplete.pl strips out those
2167 * calls and converts them into entries in tcpatterns[], which are evaluated
2168 * by the calling loop in psql_completion(). Successful matches result in
2169 * calls to this function with the appropriate pattern_id, causing just the
2170 * corresponding switch case to be executed.
2171 *
2172 * If-conditions in this function can be more complex than a single *Matches
2173 * function call in one of two ways (but not both!). They can be OR's
2174 * of *Matches calls, such as
2175 * else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
2176 * Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
2177 * or they can be a *Matches call AND'ed with some other condition, e.g.
2178 * else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) &&
2179 * !ends_with(prev_wd, ','))
2180 * The former case is transformed into multiple tcpatterns[] entries and
2181 * multiple case labels for the same bit of code. The latter case is
2182 * transformed into a case label and a contained if-statement.
2183 *
2184 * This is split out of psql_completion() primarily to separate code that
2185 * gen_tabcomplete.pl should process from code that it should not, although
2186 * doing so also helps to avoid extra indentation of this code.
2187 *
2188 * Returns a matches list, or NULL if no match.
2189 */
2190static char **
2192 const char *text, int start, int end,
2194{
2195 /* This is the variable we'll return. */
2196 char **matches = NULL;
2197
2198 /* Dummy statement, allowing all the match rules to look like "else if" */
2199 if (0)
2200 {
2201 /* skip */
2202 }
2203
2204 /* gen_tabcomplete.pl begins special processing here */
2205 /* BEGIN GEN_TABCOMPLETE */
2206
2207/* CREATE */
2208 /* complete with something you can create */
2209 else if (TailMatches("CREATE"))
2210 {
2211 /* only some object types can be created as part of CREATE SCHEMA */
2212 if (HeadMatches("CREATE", "SCHEMA"))
2213 COMPLETE_WITH("TABLE", "VIEW", "INDEX", "SEQUENCE", "TRIGGER",
2214 /* for INDEX and TABLE/SEQUENCE, respectively */
2215 "UNIQUE", "UNLOGGED");
2216 else
2218 }
2219 /* complete with something you can create or replace */
2220 else if (TailMatches("CREATE", "OR", "REPLACE"))
2221 COMPLETE_WITH("FUNCTION", "PROCEDURE", "LANGUAGE", "RULE", "VIEW",
2222 "AGGREGATE", "TRANSFORM", "TRIGGER");
2223
2224/* DROP, but not DROP embedded in other commands */
2225 /* complete with something you can drop */
2226 else if (Matches("DROP"))
2228
2229/* ALTER */
2230
2231 /* ALTER TABLE */
2232 else if (Matches("ALTER", "TABLE"))
2234 "ALL IN TABLESPACE");
2235
2236 /* ALTER something */
2237 else if (Matches("ALTER"))
2239 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
2240 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny))
2241 COMPLETE_WITH("SET TABLESPACE", "OWNED BY");
2242 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
2243 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
2245 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
2246 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
2247 COMPLETE_WITH("SET TABLESPACE");
2248 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
2249 else if (Matches("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
2250 COMPLETE_WITH("(");
2251 /* ALTER AGGREGATE <name> (...) */
2252 else if (Matches("ALTER", "AGGREGATE", MatchAny, MatchAny))
2253 {
2254 if (ends_with(prev_wd, ')'))
2255 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
2256 else
2258 }
2259 /* ALTER FUNCTION <name> (...) */
2260 else if (Matches("ALTER", "FUNCTION", MatchAny, MatchAny))
2261 {
2262 if (ends_with(prev_wd, ')'))
2264 else
2266 }
2267 /* ALTER PROCEDURE <name> (...) */
2268 else if (Matches("ALTER", "PROCEDURE", MatchAny, MatchAny))
2269 {
2270 if (ends_with(prev_wd, ')'))
2272 else
2274 }
2275 /* ALTER ROUTINE <name> (...) */
2276 else if (Matches("ALTER", "ROUTINE", MatchAny, MatchAny))
2277 {
2278 if (ends_with(prev_wd, ')'))
2280 else
2282 }
2283 /* ALTER FUNCTION|ROUTINE <name> (...) PARALLEL */
2284 else if (Matches("ALTER", "FUNCTION|ROUTINE", MatchAny, MatchAny, "PARALLEL"))
2285 COMPLETE_WITH("RESTRICTED", "SAFE", "UNSAFE");
2286 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) [EXTERNAL] SECURITY */
2287 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SECURITY") ||
2288 Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "EXTERNAL", "SECURITY"))
2289 COMPLETE_WITH("DEFINER", "INVOKER");
2290 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) RESET */
2291 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "RESET"))
2293 "ALL");
2294 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) SET */
2295 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SET"))
2297 "SCHEMA");
2298
2299 /* ALTER PUBLICATION <name> */
2300 else if (Matches("ALTER", "PUBLICATION", MatchAny))
2301 COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME TO", "SET");
2302 /* ALTER PUBLICATION <name> ADD */
2303 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD"))
2304 COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
2305 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
2307 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
2308 ends_with(prev_wd, ','))
2310
2311 /*
2312 * "ALTER PUBLICATION <name> SET TABLE <name> WHERE (" - complete with
2313 * table attributes
2314 *
2315 * "ALTER PUBLICATION <name> ADD TABLE <name> WHERE (" - complete with
2316 * table attributes
2317 */
2318 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "WHERE"))
2319 COMPLETE_WITH("(");
2320 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "("))
2322 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
2323 !TailMatches("WHERE", "(*)"))
2324 COMPLETE_WITH(",", "WHERE (");
2325 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
2326 COMPLETE_WITH(",");
2327 /* ALTER PUBLICATION <name> DROP */
2328 else if (Matches("ALTER", "PUBLICATION", MatchAny, "DROP"))
2329 COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
2330 /* ALTER PUBLICATION <name> SET */
2331 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
2332 COMPLETE_WITH("(", "ALL SEQUENCES", "ALL TABLES", "TABLES IN SCHEMA", "TABLE");
2333 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL"))
2334 COMPLETE_WITH("SEQUENCES", "TABLES");
2335 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES"))
2336 COMPLETE_WITH("EXCEPT ( TABLE");
2337 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT"))
2338 COMPLETE_WITH("( TABLE");
2339 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "("))
2340 COMPLETE_WITH("TABLE");
2341 /* Complete "ALTER PUBLICATION <name> FOR TABLE" with "<table>, ..." */
2342 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "(", "TABLE"))
2344 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd, ','))
2346 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd, ','))
2347 COMPLETE_WITH(")");
2348 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|DROP|SET", "TABLES", "IN", "SCHEMA"))
2350 " AND nspname NOT LIKE E'pg\\\\_%%'",
2351 "CURRENT_SCHEMA");
2352 /* ALTER PUBLICATION <name> SET ( */
2353 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "SET", "("))
2354 COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root");
2355 /* ALTER SUBSCRIPTION <name> */
2356 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny))
2357 COMPLETE_WITH("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
2358 "RENAME TO", "REFRESH PUBLICATION", "REFRESH SEQUENCES",
2359 "SERVER", "SET", "SKIP (", "ADD PUBLICATION", "DROP PUBLICATION");
2360 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SERVER"))
2362 /* ALTER SUBSCRIPTION <name> REFRESH */
2363 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH"))
2364 COMPLETE_WITH("PUBLICATION", "SEQUENCES");
2365 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
2366 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH", "PUBLICATION", "WITH", "("))
2367 COMPLETE_WITH("copy_data");
2368 /* ALTER SUBSCRIPTION <name> SET */
2369 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
2370 COMPLETE_WITH("(", "PUBLICATION");
2371 /* ALTER SUBSCRIPTION <name> SET ( */
2372 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "("))
2373 COMPLETE_WITH("binary", "disable_on_error", "failover",
2374 "max_retention_duration", "origin",
2375 "password_required", "retain_dead_tuples",
2376 "run_as_owner", "slot_name", "streaming",
2377 "synchronous_commit", "two_phase");
2378 /* ALTER SUBSCRIPTION <name> SKIP ( */
2379 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SKIP", "("))
2380 COMPLETE_WITH("lsn");
2381 /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
2382 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "PUBLICATION"))
2383 {
2384 /* complete with nothing here as this refers to remote publications */
2385 }
2386 /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> */
2387 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN,
2388 "ADD|DROP|SET", "PUBLICATION", MatchAny))
2389 COMPLETE_WITH("WITH (");
2390 /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> WITH ( */
2391 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN,
2392 "ADD|DROP|SET", "PUBLICATION", MatchAny, "WITH", "("))
2393 COMPLETE_WITH("copy_data", "refresh");
2394
2395 /* ALTER SCHEMA <name> */
2396 else if (Matches("ALTER", "SCHEMA", MatchAny))
2397 COMPLETE_WITH("OWNER TO", "RENAME TO");
2398
2399 /* ALTER COLLATION <name> */
2400 else if (Matches("ALTER", "COLLATION", MatchAny))
2401 COMPLETE_WITH("OWNER TO", "REFRESH VERSION", "RENAME TO", "SET SCHEMA");
2402
2403 /* ALTER CONVERSION <name> */
2404 else if (Matches("ALTER", "CONVERSION", MatchAny))
2405 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
2406
2407 /* ALTER DATABASE <name> */
2408 else if (Matches("ALTER", "DATABASE", MatchAny))
2409 COMPLETE_WITH("RESET", "SET", "OWNER TO", "REFRESH COLLATION VERSION", "RENAME TO",
2410 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
2411 "CONNECTION LIMIT");
2412
2413 /* ALTER DATABASE <name> RESET */
2414 else if (Matches("ALTER", "DATABASE", MatchAny, "RESET"))
2415 {
2418 }
2419
2420 /* ALTER DATABASE <name> SET TABLESPACE */
2421 else if (Matches("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE"))
2423
2424 /* ALTER EVENT TRIGGER */
2425 else if (Matches("ALTER", "EVENT", "TRIGGER"))
2427
2428 /* ALTER EVENT TRIGGER <name> */
2429 else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny))
2430 COMPLETE_WITH("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
2431
2432 /* ALTER EVENT TRIGGER <name> ENABLE */
2433 else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
2434 COMPLETE_WITH("REPLICA", "ALWAYS");
2435
2436 /* ALTER EXTENSION <name> */
2437 else if (Matches("ALTER", "EXTENSION", MatchAny))
2438 COMPLETE_WITH("ADD", "DROP", "UPDATE", "SET SCHEMA");
2439
2440 /* ALTER EXTENSION <name> ADD|DROP */
2441 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP"))
2442 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
2443 "CONVERSION", "DOMAIN", "EVENT TRIGGER", "FOREIGN",
2444 "FUNCTION", "MATERIALIZED VIEW", "OPERATOR",
2445 "LANGUAGE", "PROCEDURE", "ROUTINE", "SCHEMA",
2446 "SEQUENCE", "SERVER", "TABLE", "TEXT SEARCH",
2447 "TRANSFORM FOR", "TYPE", "VIEW");
2448
2449 /* ALTER EXTENSION <name> ADD|DROP FOREIGN */
2450 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "FOREIGN"))
2451 COMPLETE_WITH("DATA WRAPPER", "TABLE");
2452
2453 /* ALTER EXTENSION <name> ADD|DROP OPERATOR */
2454 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "OPERATOR"))
2455 COMPLETE_WITH("CLASS", "FAMILY");
2456
2457 /* ALTER EXTENSION <name> ADD|DROP TEXT SEARCH */
2458 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "TEXT", "SEARCH"))
2459 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2460
2461 /* ALTER EXTENSION <name> UPDATE */
2462 else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE"))
2463 COMPLETE_WITH("TO");
2464
2465 /* ALTER EXTENSION <name> UPDATE TO */
2466 else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
2467 {
2470 }
2471
2472 /* ALTER FOREIGN */
2473 else if (Matches("ALTER", "FOREIGN"))
2474 COMPLETE_WITH("DATA WRAPPER", "TABLE");
2475
2476 /* ALTER FOREIGN DATA WRAPPER <name> */
2477 else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2478 COMPLETE_WITH("CONNECTION", "HANDLER", "NO",
2479 "OPTIONS", "OWNER TO", "RENAME TO", "VALIDATOR");
2480 else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny, "NO"))
2481 COMPLETE_WITH("CONNECTION", "HANDLER", "VALIDATOR");
2482
2483 /* ALTER FOREIGN TABLE <name> */
2484 else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny))
2485 COMPLETE_WITH("ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE",
2486 "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO",
2487 "RENAME", "SET", "VALIDATE CONSTRAINT");
2488
2489 /* ALTER INDEX */
2490 else if (Matches("ALTER", "INDEX"))
2492 "ALL IN TABLESPACE");
2493 /* ALTER INDEX <name> */
2494 else if (Matches("ALTER", "INDEX", MatchAny))
2495 COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
2496 "RESET", "ATTACH PARTITION",
2497 "DEPENDS ON EXTENSION", "NO DEPENDS ON EXTENSION");
2498 else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH"))
2499 COMPLETE_WITH("PARTITION");
2500 else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
2502 /* ALTER INDEX <name> ALTER */
2503 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER"))
2504 COMPLETE_WITH("COLUMN");
2505 /* ALTER INDEX <name> ALTER COLUMN */
2506 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN"))
2507 {
2510 }
2511 /* ALTER INDEX <name> ALTER COLUMN <colnum> */
2512 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
2513 COMPLETE_WITH("SET STATISTICS");
2514 /* ALTER INDEX <name> ALTER COLUMN <colnum> SET */
2515 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET"))
2516 COMPLETE_WITH("STATISTICS");
2517 /* ALTER INDEX <name> ALTER COLUMN <colnum> SET STATISTICS */
2518 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS"))
2519 {
2520 /* Enforce no completion here, as an integer has to be specified */
2521 }
2522 /* ALTER INDEX <name> SET */
2523 else if (Matches("ALTER", "INDEX", MatchAny, "SET"))
2524 COMPLETE_WITH("(", "TABLESPACE");
2525 /* ALTER INDEX <name> RESET */
2526 else if (Matches("ALTER", "INDEX", MatchAny, "RESET"))
2527 COMPLETE_WITH("(");
2528 /* ALTER INDEX <foo> SET|RESET ( */
2529 else if (Matches("ALTER", "INDEX", MatchAny, "RESET", "("))
2530 COMPLETE_WITH("fillfactor",
2531 "deduplicate_items", /* BTREE */
2532 "fastupdate", "gin_pending_list_limit", /* GIN */
2533 "buffering", /* GiST */
2534 "pages_per_range", "autosummarize" /* BRIN */
2535 );
2536 else if (Matches("ALTER", "INDEX", MatchAny, "SET", "("))
2537 COMPLETE_WITH("fillfactor =",
2538 "deduplicate_items =", /* BTREE */
2539 "fastupdate =", "gin_pending_list_limit =", /* GIN */
2540 "buffering =", /* GiST */
2541 "pages_per_range =", "autosummarize =" /* BRIN */
2542 );
2543 else if (Matches("ALTER", "INDEX", MatchAny, "NO", "DEPENDS"))
2544 COMPLETE_WITH("ON EXTENSION");
2545 else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS"))
2546 COMPLETE_WITH("ON EXTENSION");
2547
2548 /* ALTER LANGUAGE <name> */
2549 else if (Matches("ALTER", "LANGUAGE", MatchAny))
2550 COMPLETE_WITH("OWNER TO", "RENAME TO");
2551
2552 /* ALTER LARGE OBJECT <oid> */
2553 else if (Matches("ALTER", "LARGE", "OBJECT", MatchAny))
2554 COMPLETE_WITH("OWNER TO");
2555
2556 /* ALTER MATERIALIZED VIEW */
2557 else if (Matches("ALTER", "MATERIALIZED", "VIEW"))
2559 "ALL IN TABLESPACE");
2560
2561 /* ALTER USER,ROLE <name> */
2562 else if (Matches("ALTER", "USER|ROLE", MatchAny) &&
2563 !TailMatches("USER", "MAPPING"))
2564 COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2565 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2566 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2567 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2568 "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
2569 "VALID UNTIL", "WITH");
2570 /* ALTER USER,ROLE <name> IN */
2571 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN"))
2572 COMPLETE_WITH("DATABASE");
2573 /* ALTER USER,ROLE <name> IN DATABASE */
2574 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE"))
2576 /* ALTER USER,ROLE <name> IN DATABASE <dbname> */
2577 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE", MatchAny))
2578 COMPLETE_WITH("SET", "RESET");
2579 /* ALTER USER,ROLE <name> IN DATABASE <dbname> SET */
2580 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE", MatchAny, "SET"))
2582 /* XXX missing support for ALTER ROLE <name> IN DATABASE <dbname> RESET */
2583 /* ALTER USER,ROLE <name> RESET */
2584 else if (Matches("ALTER", "USER|ROLE", MatchAny, "RESET"))
2585 {
2588 }
2589
2590 /* ALTER USER,ROLE <name> WITH */
2591 else if (Matches("ALTER", "USER|ROLE", MatchAny, "WITH"))
2592 /* Similar to the above, but don't complete "WITH" again. */
2593 COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2594 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
2595 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2596 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2597 "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
2598 "VALID UNTIL");
2599
2600 /* ALTER DEFAULT PRIVILEGES */
2601 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES"))
2602 COMPLETE_WITH("FOR", "GRANT", "IN SCHEMA", "REVOKE");
2603 /* ALTER DEFAULT PRIVILEGES FOR */
2604 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
2605 COMPLETE_WITH("ROLE");
2606 /* ALTER DEFAULT PRIVILEGES IN */
2607 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
2608 COMPLETE_WITH("SCHEMA");
2609 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
2610 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2611 MatchAny))
2612 COMPLETE_WITH("GRANT", "REVOKE", "IN SCHEMA");
2613 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
2614 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2615 MatchAny))
2616 COMPLETE_WITH("GRANT", "REVOKE", "FOR ROLE");
2617 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
2618 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2619 MatchAny, "FOR"))
2620 COMPLETE_WITH("ROLE");
2621 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
2622 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
2623 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2624 MatchAny, "IN", "SCHEMA", MatchAny) ||
2625 Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2626 MatchAny, "FOR", "ROLE|USER", MatchAny))
2627 COMPLETE_WITH("GRANT", "REVOKE");
2628 /* ALTER DOMAIN <name> */
2629 else if (Matches("ALTER", "DOMAIN", MatchAny))
2630 COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME", "SET",
2631 "VALIDATE CONSTRAINT");
2632 /* ALTER DOMAIN <sth> ADD */
2633 else if (Matches("ALTER", "DOMAIN", MatchAny, "ADD"))
2634 COMPLETE_WITH("CONSTRAINT", "NOT NULL", "CHECK (");
2635 /* ALTER DOMAIN <sth> ADD CONSTRAINT <sth> */
2636 else if (Matches("ALTER", "DOMAIN", MatchAny, "ADD", "CONSTRAINT", MatchAny))
2637 COMPLETE_WITH("NOT NULL", "CHECK (");
2638 /* ALTER DOMAIN <sth> DROP */
2639 else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP"))
2640 COMPLETE_WITH("CONSTRAINT", "DEFAULT", "NOT NULL");
2641 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
2642 else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
2643 {
2646 }
2647 /* ALTER DOMAIN <sth> RENAME */
2648 else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME"))
2649 COMPLETE_WITH("CONSTRAINT", "TO");
2650 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
2651 else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
2652 COMPLETE_WITH("TO");
2653
2654 /* ALTER DOMAIN <sth> SET */
2655 else if (Matches("ALTER", "DOMAIN", MatchAny, "SET"))
2656 COMPLETE_WITH("DEFAULT", "NOT NULL", "SCHEMA");
2657 /* ALTER SEQUENCE <name> */
2658 else if (Matches("ALTER", "SEQUENCE", MatchAny))
2659 COMPLETE_WITH("AS", "INCREMENT", "MINVALUE", "MAXVALUE", "RESTART",
2660 "START", "NO", "CACHE", "CYCLE", "SET", "OWNED BY",
2661 "OWNER TO", "RENAME TO");
2662 /* ALTER SEQUENCE <name> AS */
2663 else if (TailMatches("ALTER", "SEQUENCE", MatchAny, "AS"))
2664 COMPLETE_WITH_CS("smallint", "integer", "bigint");
2665 /* ALTER SEQUENCE <name> NO */
2666 else if (Matches("ALTER", "SEQUENCE", MatchAny, "NO"))
2667 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
2668 /* ALTER SEQUENCE <name> SET */
2669 else if (Matches("ALTER", "SEQUENCE", MatchAny, "SET"))
2670 COMPLETE_WITH("SCHEMA", "LOGGED", "UNLOGGED");
2671 /* ALTER SERVER <name> */
2672 else if (Matches("ALTER", "SERVER", MatchAny))
2673 COMPLETE_WITH("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
2674 /* ALTER SERVER <name> VERSION <version> */
2675 else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
2676 COMPLETE_WITH("OPTIONS");
2677 /* ALTER SYSTEM SET, RESET, RESET ALL */
2678 else if (Matches("ALTER", "SYSTEM"))
2679 COMPLETE_WITH("SET", "RESET");
2680 else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
2682 "ALL");
2683 else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
2684 COMPLETE_WITH("TO");
2685 /* ALTER VIEW <name> */
2686 else if (Matches("ALTER", "VIEW", MatchAny))
2687 COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME", "RESET", "SET");
2688 /* ALTER VIEW xxx RENAME */
2689 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME"))
2690 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
2691 else if (Matches("ALTER", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
2693 /* ALTER VIEW xxx ALTER [ COLUMN ] yyy */
2694 else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
2695 Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
2696 COMPLETE_WITH("SET DEFAULT", "DROP DEFAULT");
2697 /* ALTER VIEW xxx RENAME yyy */
2698 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
2699 COMPLETE_WITH("TO");
2700 /* ALTER VIEW xxx RENAME COLUMN yyy */
2701 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
2702 COMPLETE_WITH("TO");
2703 /* ALTER VIEW xxx RESET ( */
2704 else if (Matches("ALTER", "VIEW", MatchAny, "RESET"))
2705 COMPLETE_WITH("(");
2706 /* Complete ALTER VIEW xxx SET with "(" or "SCHEMA" */
2707 else if (Matches("ALTER", "VIEW", MatchAny, "SET"))
2708 COMPLETE_WITH("(", "SCHEMA");
2709 /* ALTER VIEW xxx SET|RESET ( yyy [= zzz] ) */
2710 else if (Matches("ALTER", "VIEW", MatchAny, "SET|RESET", "("))
2712 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", MatchAny))
2713 COMPLETE_WITH("=");
2714 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "check_option", "="))
2715 COMPLETE_WITH("local", "cascaded");
2716 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "security_barrier|security_invoker", "="))
2717 COMPLETE_WITH("true", "false");
2718
2719 /* ALTER MATERIALIZED VIEW <name> */
2720 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
2721 COMPLETE_WITH("ALTER COLUMN", "CLUSTER ON", "DEPENDS ON EXTENSION",
2722 "NO DEPENDS ON EXTENSION", "OWNER TO", "RENAME",
2723 "RESET (", "SET");
2724 /* ALTER MATERIALIZED VIEW xxx RENAME */
2725 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME"))
2726 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
2727 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
2729 /* ALTER MATERIALIZED VIEW xxx RENAME yyy */
2730 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
2731 COMPLETE_WITH("TO");
2732 /* ALTER MATERIALIZED VIEW xxx RENAME COLUMN yyy */
2733 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
2734 COMPLETE_WITH("TO");
2735 /* ALTER MATERIALIZED VIEW xxx SET */
2736 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET"))
2737 COMPLETE_WITH("(", "ACCESS METHOD", "SCHEMA", "TABLESPACE", "WITHOUT CLUSTER");
2738 /* ALTER MATERIALIZED VIEW xxx SET ACCESS METHOD */
2739 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET", "ACCESS", "METHOD"))
2741
2742 /* ALTER POLICY <name> */
2743 else if (Matches("ALTER", "POLICY"))
2745 /* ALTER POLICY <name> ON */
2746 else if (Matches("ALTER", "POLICY", MatchAny))
2747 COMPLETE_WITH("ON");
2748 /* ALTER POLICY <name> ON <table> */
2749 else if (Matches("ALTER", "POLICY", MatchAny, "ON"))
2750 {
2753 }
2754 /* ALTER POLICY <name> ON <table> - show options */
2755 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny))
2756 COMPLETE_WITH("RENAME TO", "TO", "USING (", "WITH CHECK (");
2757 /* ALTER POLICY <name> ON <table> TO <role> */
2758 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2761 /* ALTER POLICY <name> ON <table> USING ( */
2762 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2763 COMPLETE_WITH("(");
2764 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
2765 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
2766 COMPLETE_WITH("(");
2767
2768 /* ALTER PROPERTY GRAPH */
2769 else if (Matches("ALTER", "PROPERTY", "GRAPH"))
2771 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny))
2772 COMPLETE_WITH("ADD", "ALTER", "DROP", "OWNER TO", "RENAME TO", "SET SCHEMA");
2773 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD|ALTER|DROP"))
2774 COMPLETE_WITH("VERTEX", "EDGE");
2775 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD|DROP", "VERTEX|EDGE"))
2776 COMPLETE_WITH("TABLES");
2777 else if (HeadMatches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD") && TailMatches("EDGE"))
2778 COMPLETE_WITH("TABLES");
2779 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ALTER", "VERTEX|EDGE"))
2780 COMPLETE_WITH("TABLE");
2781
2782 /* ALTER RULE <name>, add ON */
2783 else if (Matches("ALTER", "RULE", MatchAny))
2784 COMPLETE_WITH("ON");
2785
2786 /* If we have ALTER RULE <name> ON, then add the correct tablename */
2787 else if (Matches("ALTER", "RULE", MatchAny, "ON"))
2788 {
2791 }
2792
2793 /* ALTER RULE <name> ON <name> */
2794 else if (Matches("ALTER", "RULE", MatchAny, "ON", MatchAny))
2795 COMPLETE_WITH("RENAME TO");
2796
2797 /* ALTER STATISTICS <name> */
2798 else if (Matches("ALTER", "STATISTICS", MatchAny))
2799 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA", "SET STATISTICS");
2800 /* ALTER STATISTICS <name> SET */
2801 else if (Matches("ALTER", "STATISTICS", MatchAny, "SET"))
2802 COMPLETE_WITH("SCHEMA", "STATISTICS");
2803
2804 /* ALTER TRIGGER <name>, add ON */
2805 else if (Matches("ALTER", "TRIGGER", MatchAny))
2806 COMPLETE_WITH("ON");
2807
2808 else if (Matches("ALTER", "TRIGGER", MatchAny, "ON"))
2809 {
2812 }
2813
2814 /* ALTER TRIGGER <name> ON <name> */
2815 else if (Matches("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
2816 COMPLETE_WITH("RENAME TO", "DEPENDS ON EXTENSION",
2817 "NO DEPENDS ON EXTENSION");
2818
2819 /*
2820 * If we detect ALTER TABLE <name>, suggest sub commands
2821 */
2822 else if (Matches("ALTER", "TABLE", MatchAny))
2823 COMPLETE_WITH("ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP",
2824 "ENABLE", "INHERIT", "NO", "RENAME", "RESET",
2825 "OWNER TO", "SET", "VALIDATE CONSTRAINT",
2826 "REPLICA IDENTITY", "ATTACH PARTITION",
2827 "DETACH PARTITION", "FORCE ROW LEVEL SECURITY",
2828 "SPLIT PARTITION", "MERGE PARTITIONS (",
2829 "OF", "NOT OF");
2830 /* ALTER TABLE xxx ADD */
2831 else if (Matches("ALTER", "TABLE", MatchAny, "ADD"))
2832 {
2833 /*
2834 * make sure to keep this list and the MatchAnyExcept() below in sync
2835 */
2836 COMPLETE_WITH("COLUMN", "CONSTRAINT", "CHECK (", "NOT NULL", "UNIQUE",
2837 "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
2838 }
2839 /* ALTER TABLE xxx ADD [COLUMN] yyy */
2840 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN", MatchAny) ||
2841 Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAnyExcept("COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|NOT|EXCLUDE|FOREIGN")))
2843 /* ALTER TABLE xxx ADD CONSTRAINT yyy */
2844 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny))
2845 COMPLETE_WITH("CHECK (", "NOT NULL", "UNIQUE", "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
2846 /* ALTER TABLE xxx ADD NOT NULL */
2847 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "NOT", "NULL"))
2849 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "NOT", "NULL"))
2851 /* ALTER TABLE xxx ADD [CONSTRAINT yyy] (PRIMARY KEY|UNIQUE) */
2852 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY") ||
2853 Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE") ||
2854 Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "PRIMARY", "KEY") ||
2855 Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "UNIQUE"))
2856 COMPLETE_WITH("(", "USING INDEX");
2857 /* ALTER TABLE xxx ADD PRIMARY KEY USING INDEX */
2858 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY", "USING", "INDEX"))
2859 {
2862 }
2863 /* ALTER TABLE xxx ADD UNIQUE USING INDEX */
2864 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE", "USING", "INDEX"))
2865 {
2868 }
2869 /* ALTER TABLE xxx ADD CONSTRAINT yyy PRIMARY KEY USING INDEX */
2870 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2871 "PRIMARY", "KEY", "USING", "INDEX"))
2872 {
2875 }
2876 /* ALTER TABLE xxx ADD CONSTRAINT yyy UNIQUE USING INDEX */
2877 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2878 "UNIQUE", "USING", "INDEX"))
2879 {
2882 }
2883 /* ALTER TABLE xxx ENABLE */
2884 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE"))
2885 COMPLETE_WITH("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
2886 "TRIGGER");
2887 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
2888 COMPLETE_WITH("RULE", "TRIGGER");
2889 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
2890 {
2893 }
2894 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
2895 {
2898 }
2899 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
2900 {
2903 }
2904 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
2905 {
2908 }
2909 /* ALTER TABLE xxx INHERIT */
2910 else if (Matches("ALTER", "TABLE", MatchAny, "INHERIT"))
2912 /* ALTER TABLE xxx NO */
2913 else if (Matches("ALTER", "TABLE", MatchAny, "NO"))
2914 COMPLETE_WITH("FORCE ROW LEVEL SECURITY", "INHERIT");
2915 /* ALTER TABLE xxx NO INHERIT */
2916 else if (Matches("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
2918 /* ALTER TABLE xxx DISABLE */
2919 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE"))
2920 COMPLETE_WITH("ROW LEVEL SECURITY", "RULE", "TRIGGER");
2921 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
2922 {
2925 }
2926 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
2927 {
2930 }
2931
2932 /* ALTER TABLE xxx ALTER */
2933 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER"))
2934 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT");
2935
2936 /* ALTER TABLE xxx RENAME */
2937 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME"))
2938 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT", "TO");
2939 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
2941
2942 /* ALTER TABLE xxx RENAME yyy */
2943 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
2944 COMPLETE_WITH("TO");
2945
2946 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
2947 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
2948 COMPLETE_WITH("TO");
2949
2950 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
2951 else if (Matches("ALTER", "TABLE", MatchAny, "DROP"))
2952 COMPLETE_WITH("COLUMN", "CONSTRAINT");
2953 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
2954 else if (Matches("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
2956 /* ALTER TABLE <sth> ALTER|DROP|RENAME CONSTRAINT <constraint> */
2957 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME", "CONSTRAINT"))
2958 {
2961 }
2962 /* ALTER TABLE <sth> VALIDATE CONSTRAINT <non-validated constraint> */
2963 else if (Matches("ALTER", "TABLE", MatchAny, "VALIDATE", "CONSTRAINT"))
2964 {
2967 }
2968 /* ALTER TABLE ALTER [COLUMN] <foo> */
2969 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
2970 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
2971 COMPLETE_WITH("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
2972 /* ALTER TABLE ALTER [COLUMN] <foo> ADD */
2973 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD") ||
2974 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD"))
2975 COMPLETE_WITH("GENERATED");
2976 /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
2977 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED") ||
2978 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED"))
2979 COMPLETE_WITH("ALWAYS", "BY DEFAULT");
2980 /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
2981 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2982 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2983 Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT") ||
2984 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT"))
2985 COMPLETE_WITH("AS IDENTITY");
2986 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
2987 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
2988 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
2989 COMPLETE_WITH("(", "COMPRESSION", "DATA TYPE", "DEFAULT", "EXPRESSION", "GENERATED", "NOT NULL",
2990 "STATISTICS", "STORAGE",
2991 /* a subset of ALTER SEQUENCE options */
2992 "INCREMENT", "MINVALUE", "MAXVALUE", "START", "NO", "CACHE", "CYCLE");
2993 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
2994 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
2995 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
2996 COMPLETE_WITH("n_distinct", "n_distinct_inherited");
2997 /* ALTER TABLE ALTER [COLUMN] <foo> SET COMPRESSION */
2998 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "COMPRESSION") ||
2999 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "COMPRESSION"))
3000 COMPLETE_WITH("DEFAULT", "PGLZ", "LZ4");
3001 /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION */
3002 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION") ||
3003 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION"))
3004 COMPLETE_WITH("AS");
3005 /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION AS */
3006 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION", "AS") ||
3007 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION", "AS"))
3008 COMPLETE_WITH("(");
3009 /* ALTER TABLE ALTER [COLUMN] <foo> SET GENERATED */
3010 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "GENERATED") ||
3011 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "GENERATED"))
3012 COMPLETE_WITH("ALWAYS", "BY DEFAULT");
3013 /* ALTER TABLE ALTER [COLUMN] <foo> SET NO */
3014 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "NO") ||
3015 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "NO"))
3016 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
3017 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
3018 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
3019 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
3020 COMPLETE_WITH("DEFAULT", "PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
3021 /* ALTER TABLE ALTER [COLUMN] <foo> SET STATISTICS */
3022 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS") ||
3023 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STATISTICS"))
3024 {
3025 /* Enforce no completion here, as an integer has to be specified */
3026 }
3027 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
3028 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
3029 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
3030 COMPLETE_WITH("DEFAULT", "EXPRESSION", "IDENTITY", "NOT NULL");
3031 else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER"))
3032 COMPLETE_WITH("ON");
3033 else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
3034 {
3037 }
3038 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
3039 else if (Matches("ALTER", "TABLE", MatchAny, "SET"))
3040 COMPLETE_WITH("(", "ACCESS METHOD", "LOGGED", "SCHEMA",
3041 "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT");
3042
3043 /*
3044 * If we have ALTER TABLE <sth> SET ACCESS METHOD provide a list of table
3045 * AMs.
3046 */
3047 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "ACCESS", "METHOD"))
3049 "DEFAULT");
3050
3051 /*
3052 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
3053 * tablespaces
3054 */
3055 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
3057 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
3058 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
3059 COMPLETE_WITH("CLUSTER", "OIDS");
3060 /* ALTER TABLE <foo> RESET */
3061 else if (Matches("ALTER", "TABLE", MatchAny, "RESET"))
3062 COMPLETE_WITH("(");
3063 /* ALTER TABLE <foo> SET|RESET ( */
3064 else if (Matches("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
3066 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
3067 {
3070 }
3071 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
3072 COMPLETE_WITH("INDEX");
3073 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
3074 COMPLETE_WITH("FULL", "NOTHING", "DEFAULT", "USING");
3075 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA"))
3076 COMPLETE_WITH("IDENTITY");
3077
3078 /*
3079 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
3080 * tables.
3081 */
3082 else if (Matches("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
3084 /* Limited completion support for partition bound specification */
3085 else if (TailMatches("ATTACH", "PARTITION", MatchAny))
3086 COMPLETE_WITH("FOR VALUES", "DEFAULT");
3087 else if (TailMatches("FOR", "VALUES"))
3088 COMPLETE_WITH("FROM (", "IN (", "WITH (");
3089
3090 /*
3091 * If we have ALTER TABLE <foo> DETACH|SPLIT PARTITION, provide a list of
3092 * partitions of <foo>.
3093 */
3094 else if (Matches("ALTER", "TABLE", MatchAny, "DETACH|SPLIT", "PARTITION"))
3095 {
3098 }
3099 else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION", MatchAny))
3100 COMPLETE_WITH("CONCURRENTLY", "FINALIZE");
3101
3102 /* ALTER TABLE <name> SPLIT PARTITION <name> */
3103 else if (Matches("ALTER", "TABLE", MatchAny, "SPLIT", "PARTITION", MatchAny))
3104 COMPLETE_WITH("INTO ( PARTITION");
3105
3106 /* ALTER TABLE <name> MERGE PARTITIONS ( */
3107 else if (Matches("ALTER", "TABLE", MatchAny, "MERGE", "PARTITIONS", "("))
3108 {
3111 }
3112 else if (Matches("ALTER", "TABLE", MatchAny, "MERGE", "PARTITIONS", "(*)"))
3113 COMPLETE_WITH("INTO");
3114
3115 /* ALTER TABLE <name> OF */
3116 else if (Matches("ALTER", "TABLE", MatchAny, "OF"))
3118
3119 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
3120 else if (Matches("ALTER", "TABLESPACE", MatchAny))
3121 COMPLETE_WITH("RENAME TO", "OWNER TO", "SET", "RESET");
3122 /* ALTER TABLESPACE <foo> SET|RESET */
3123 else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
3124 COMPLETE_WITH("(");
3125 /* ALTER TABLESPACE <foo> SET|RESET ( */
3126 else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
3127 COMPLETE_WITH("seq_page_cost", "random_page_cost",
3128 "effective_io_concurrency", "maintenance_io_concurrency");
3129
3130 /* ALTER TEXT SEARCH */
3131 else if (Matches("ALTER", "TEXT", "SEARCH"))
3132 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3133 else if (Matches("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
3134 COMPLETE_WITH("RENAME TO", "SET SCHEMA");
3135 else if (Matches("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
3136 COMPLETE_WITH("(", "OWNER TO", "RENAME TO", "SET SCHEMA");
3137 else if (Matches("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
3138 COMPLETE_WITH("ADD MAPPING FOR", "ALTER MAPPING",
3139 "DROP MAPPING FOR",
3140 "OWNER TO", "RENAME TO", "SET SCHEMA");
3141
3142 /* complete ALTER TYPE <foo> with actions */
3143 else if (Matches("ALTER", "TYPE", MatchAny))
3144 COMPLETE_WITH("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
3145 "DROP ATTRIBUTE",
3146 "OWNER TO", "RENAME", "SET SCHEMA", "SET (");
3147 /* complete ALTER TYPE <foo> ADD with actions */
3148 else if (Matches("ALTER", "TYPE", MatchAny, "ADD"))
3149 COMPLETE_WITH("ATTRIBUTE", "VALUE");
3150 /* ALTER TYPE <foo> RENAME */
3151 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME"))
3152 COMPLETE_WITH("ATTRIBUTE", "TO", "VALUE");
3153 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
3154 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
3155 COMPLETE_WITH("TO");
3156 /* ALTER TYPE xxx RENAME ATTRIBUTE yyy TO zzz */
3157 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny, "TO", MatchAny))
3158 COMPLETE_WITH("CASCADE", "RESTRICT");
3159
3160 /*
3161 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
3162 * of attributes
3163 */
3164 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
3166 /* complete ALTER TYPE ADD ATTRIBUTE <foo> with list of types */
3167 else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny))
3169 /* complete ALTER TYPE ADD ATTRIBUTE <foo> <footype> with CASCADE/RESTRICT */
3170 else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny, MatchAny))
3171 COMPLETE_WITH("CASCADE", "RESTRICT");
3172 /* complete ALTER TYPE DROP ATTRIBUTE <foo> with CASCADE/RESTRICT */
3173 else if (Matches("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE", MatchAny))
3174 COMPLETE_WITH("CASCADE", "RESTRICT");
3175 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
3176 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
3177 COMPLETE_WITH("TYPE");
3178 /* ALTER TYPE ALTER ATTRIBUTE <foo> TYPE <footype> */
3179 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny, "TYPE", MatchAny))
3180 COMPLETE_WITH("CASCADE", "RESTRICT");
3181 /* complete ALTER TYPE <sth> RENAME VALUE with list of enum values */
3182 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
3184 /* ALTER TYPE <foo> SET */
3185 else if (Matches("ALTER", "TYPE", MatchAny, "SET"))
3186 COMPLETE_WITH("(", "SCHEMA");
3187 /* complete ALTER TYPE <foo> SET ( with settable properties */
3188 else if (Matches("ALTER", "TYPE", MatchAny, "SET", "("))
3189 COMPLETE_WITH("ANALYZE", "RECEIVE", "SEND", "STORAGE", "SUBSCRIPT",
3190 "TYPMOD_IN", "TYPMOD_OUT");
3191
3192 /* complete ALTER GROUP <foo> */
3193 else if (Matches("ALTER", "GROUP", MatchAny))
3194 COMPLETE_WITH("ADD USER", "DROP USER", "RENAME TO");
3195 /* complete ALTER GROUP <foo> ADD|DROP with USER */
3196 else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP"))
3197 COMPLETE_WITH("USER");
3198 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
3199 else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
3201
3202/*
3203 * ANALYZE [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
3204 * ANALYZE [ VERBOSE ] [ [ ONLY ] table_and_columns [, ...] ]
3205 */
3206 else if (Matches("ANALYZE"))
3208 "(", "VERBOSE", "ONLY");
3209 else if (Matches("ANALYZE", "VERBOSE"))
3211 "ONLY");
3212 else if (HeadMatches("ANALYZE", "(*") &&
3213 !HeadMatches("ANALYZE", "(*)"))
3214 {
3215 /*
3216 * This fires if we're in an unfinished parenthesized option list.
3217 * get_previous_words treats a completed parenthesized option list as
3218 * one word, so the above test is correct.
3219 */
3220 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3221 COMPLETE_WITH("VERBOSE", "SKIP_LOCKED", "BUFFER_USAGE_LIMIT");
3222 else if (TailMatches("VERBOSE|SKIP_LOCKED"))
3223 COMPLETE_WITH("ON", "OFF");
3224 }
3225 else if (Matches("ANALYZE", "(*)"))
3227 "ONLY");
3228 else if (Matches("ANALYZE", MatchAnyN, "("))
3229 /* "ANALYZE (" should be caught above, so assume we want columns */
3231 else if (HeadMatches("ANALYZE"))
3233
3234/* BEGIN */
3235 else if (Matches("BEGIN"))
3236 COMPLETE_WITH("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3237/* END, ABORT */
3238 else if (Matches("END|ABORT"))
3239 COMPLETE_WITH("AND", "WORK", "TRANSACTION");
3240/* COMMIT */
3241 else if (Matches("COMMIT"))
3242 COMPLETE_WITH("AND", "WORK", "TRANSACTION", "PREPARED");
3243/* RELEASE SAVEPOINT */
3244 else if (Matches("RELEASE"))
3245 COMPLETE_WITH("SAVEPOINT");
3246/* ROLLBACK */
3247 else if (Matches("ROLLBACK"))
3248 COMPLETE_WITH("AND", "WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
3249 else if (Matches("ABORT|END|COMMIT|ROLLBACK", "AND"))
3250 COMPLETE_WITH("CHAIN");
3251/* CALL */
3252 else if (Matches("CALL"))
3254 else if (Matches("CALL", MatchAny))
3255 COMPLETE_WITH("(");
3256/* CHECKPOINT */
3257 else if (Matches("CHECKPOINT"))
3258 COMPLETE_WITH("(");
3259 else if (HeadMatches("CHECKPOINT", "(*") &&
3260 !HeadMatches("CHECKPOINT", "(*)"))
3261 {
3262 /*
3263 * This fires if we're in an unfinished parenthesized option list.
3264 * get_previous_words treats a completed parenthesized option list as
3265 * one word, so the above test is correct.
3266 */
3267 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3268 COMPLETE_WITH("MODE", "FLUSH_UNLOGGED");
3269 else if (TailMatches("MODE"))
3270 COMPLETE_WITH("FAST", "SPREAD");
3271 }
3272/* CLOSE */
3273 else if (Matches("CLOSE"))
3275 "ALL");
3276/* CLUSTER */
3277 else if (Matches("CLUSTER"))
3279 "VERBOSE");
3280 else if (Matches("CLUSTER", "VERBOSE") ||
3281 Matches("CLUSTER", "(*)"))
3283 /* If we have CLUSTER <sth>, then add "USING" */
3284 else if (Matches("CLUSTER", MatchAnyExcept("VERBOSE|ON|(|(*)")))
3285 COMPLETE_WITH("USING");
3286 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
3287 else if (Matches("CLUSTER", "VERBOSE|(*)", MatchAny))
3288 COMPLETE_WITH("USING");
3289 /* If we have CLUSTER <sth> USING, then add the index as well */
3290 else if (Matches("CLUSTER", MatchAny, "USING") ||
3291 Matches("CLUSTER", "VERBOSE|(*)", MatchAny, "USING"))
3292 {
3295 }
3296 else if (HeadMatches("CLUSTER", "(*") &&
3297 !HeadMatches("CLUSTER", "(*)"))
3298 {
3299 /*
3300 * This fires if we're in an unfinished parenthesized option list.
3301 * get_previous_words treats a completed parenthesized option list as
3302 * one word, so the above test is correct.
3303 */
3304 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3305 COMPLETE_WITH("VERBOSE");
3306 }
3307
3308/* COMMENT */
3309 else if (Matches("COMMENT"))
3310 COMPLETE_WITH("ON");
3311 else if (Matches("COMMENT", "ON"))
3312 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
3313 "COLUMN", "CONSTRAINT", "CONVERSION", "DATABASE",
3314 "DOMAIN", "EXTENSION", "EVENT TRIGGER",
3315 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
3316 "FUNCTION", "INDEX", "LANGUAGE", "LARGE OBJECT",
3317 "MATERIALIZED VIEW", "OPERATOR", "POLICY",
3318 "PROCEDURE", "PROCEDURAL LANGUAGE", "PROPERTY GRAPH", "PUBLICATION", "ROLE",
3319 "ROUTINE", "RULE", "SCHEMA", "SEQUENCE", "SERVER",
3320 "STATISTICS", "SUBSCRIPTION", "TABLE",
3321 "TABLESPACE", "TEXT SEARCH", "TRANSFORM FOR",
3322 "TRIGGER", "TYPE", "VIEW");
3323 else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
3325 else if (Matches("COMMENT", "ON", "CONSTRAINT"))
3327 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny))
3328 COMPLETE_WITH("ON");
3329 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
3330 {
3333 "DOMAIN");
3334 }
3335 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON", "DOMAIN"))
3337 else if (Matches("COMMENT", "ON", "EVENT", "TRIGGER"))
3339 else if (Matches("COMMENT", "ON", "FOREIGN"))
3340 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3341 else if (Matches("COMMENT", "ON", "FOREIGN", "TABLE"))
3343 else if (Matches("COMMENT", "ON", "MATERIALIZED", "VIEW"))
3345 else if (Matches("COMMENT", "ON", "POLICY"))
3347 else if (Matches("COMMENT", "ON", "POLICY", MatchAny))
3348 COMPLETE_WITH("ON");
3349 else if (Matches("COMMENT", "ON", "POLICY", MatchAny, "ON"))
3350 {
3353 }
3354 else if (Matches("COMMENT", "ON", "PROCEDURAL", "LANGUAGE"))
3356 else if (Matches("COMMENT", "ON", "PROPERTY", "GRAPH"))
3358 else if (Matches("COMMENT", "ON", "RULE", MatchAny))
3359 COMPLETE_WITH("ON");
3360 else if (Matches("COMMENT", "ON", "RULE", MatchAny, "ON"))
3361 {
3364 }
3365 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH"))
3366 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3367 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "CONFIGURATION"))
3369 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "DICTIONARY"))
3371 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "PARSER"))
3373 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "TEMPLATE"))
3375 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR"))
3377 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny))
3378 COMPLETE_WITH("LANGUAGE");
3379 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3380 {
3383 }
3384 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny))
3385 COMPLETE_WITH("ON");
3386 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny, "ON"))
3387 {
3390 }
3391 else if (Matches("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
3392 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3393 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3394 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
3395 COMPLETE_WITH("IS");
3396
3397/* COPY */
3398
3399 /*
3400 * If we have COPY, offer list of tables or "(" (Also cover the analogous
3401 * backslash command).
3402 */
3403 else if (Matches("COPY|\\copy"))
3405 /* Complete COPY ( with legal query commands */
3406 else if (Matches("COPY|\\copy", "("))
3407 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "MERGE INTO", "WITH");
3408 /* Complete COPY <sth> */
3409 else if (Matches("COPY|\\copy", MatchAny))
3410 COMPLETE_WITH("FROM", "TO");
3411 /* Complete COPY|\copy <sth> FROM|TO with filename or STDIN/STDOUT/PROGRAM */
3412 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO"))
3413 {
3414 if (HeadMatches("COPY"))
3415 {
3416 /* COPY requires quoted filename */
3417 if (TailMatches("FROM"))
3418 COMPLETE_WITH_FILES_PLUS("", true, "STDIN", "PROGRAM");
3419 else
3420 COMPLETE_WITH_FILES_PLUS("", true, "STDOUT", "PROGRAM");
3421 }
3422 else
3423 {
3424 /* \copy supports pstdin and pstdout */
3425 if (TailMatches("FROM"))
3426 COMPLETE_WITH_FILES_PLUS("", false, "STDIN", "PSTDIN", "PROGRAM");
3427 else
3428 COMPLETE_WITH_FILES_PLUS("", false, "STDOUT", "PSTDOUT", "PROGRAM");
3429 }
3430 }
3431
3432 /* Complete COPY|\copy <sth> FROM|TO PROGRAM */
3433 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM"))
3434 COMPLETE_WITH_FILES("", HeadMatches("COPY")); /* COPY requires quoted
3435 * filename */
3436
3437 /* Complete COPY <sth> TO [PROGRAM] <sth> */
3438 else if (Matches("COPY|\\copy", MatchAny, "TO", MatchAnyExcept("PROGRAM")) ||
3439 Matches("COPY|\\copy", MatchAny, "TO", "PROGRAM", MatchAny))
3440 COMPLETE_WITH("WITH (");
3441
3442 /* Complete COPY <sth> FROM [PROGRAM] <sth> */
3443 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM")) ||
3444 Matches("COPY|\\copy", MatchAny, "FROM", "PROGRAM", MatchAny))
3445 COMPLETE_WITH("WITH (", "WHERE");
3446
3447 /* Complete COPY <sth> FROM|TO [PROGRAM] filename WITH ( */
3448 else if (HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*") ||
3449 HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*"))
3450 {
3451 if (!HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*)") &&
3452 !HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*)"))
3453 {
3454 /*
3455 * This fires if we're in an unfinished parenthesized option list.
3456 * get_previous_words treats a completed parenthesized option list
3457 * as one word, so the above tests are correct.
3458 */
3459
3460 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3461 {
3462 if (HeadMatches("COPY|\\copy", MatchAny, "FROM"))
3464 else
3466 }
3467
3468 /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
3469 else if (TailMatches("FORMAT"))
3470 COMPLETE_WITH("binary", "csv", "text", "json");
3471
3472 /* Complete COPY <sth> FROM|TO filename WITH (FREEZE */
3473 else if (TailMatches("FREEZE"))
3474 COMPLETE_WITH("true", "false");
3475
3476 /* Complete COPY <sth> FROM|TO filename WITH (HEADER */
3477 else if (TailMatches("HEADER"))
3478 COMPLETE_WITH("true", "false", "MATCH");
3479
3480 /* Complete COPY <sth> FROM filename WITH (ON_ERROR */
3481 else if (TailMatches("ON_ERROR"))
3482 COMPLETE_WITH("stop", "ignore", "set_null");
3483
3484 /* Complete COPY <sth> FROM filename WITH (LOG_VERBOSITY */
3485 else if (TailMatches("LOG_VERBOSITY"))
3486 COMPLETE_WITH("silent", "default", "verbose");
3487 }
3488
3489 /* A completed parenthesized option list should be caught below */
3490 }
3491
3492 /* Complete COPY <sth> FROM [PROGRAM] <sth> WITH (<options>) */
3493 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM"), "WITH", MatchAny) ||
3494 Matches("COPY|\\copy", MatchAny, "FROM", "PROGRAM", MatchAny, "WITH", MatchAny))
3495 COMPLETE_WITH("WHERE");
3496
3497 /* CREATE ACCESS METHOD */
3498 /* Complete "CREATE ACCESS METHOD <name>" */
3499 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny))
3500 COMPLETE_WITH("TYPE");
3501 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
3502 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
3503 COMPLETE_WITH("INDEX", "TABLE");
3504 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
3505 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
3506 COMPLETE_WITH("HANDLER");
3507
3508 /* CREATE COLLATION */
3509 else if (Matches("CREATE", "COLLATION", MatchAny))
3510 COMPLETE_WITH("(", "FROM");
3511 else if (Matches("CREATE", "COLLATION", MatchAny, "FROM"))
3513 else if (HeadMatches("CREATE", "COLLATION", MatchAny, "(*"))
3514 {
3515 if (TailMatches("(|*,"))
3516 COMPLETE_WITH("LOCALE =", "LC_COLLATE =", "LC_CTYPE =",
3517 "PROVIDER =", "DETERMINISTIC =");
3518 else if (TailMatches("PROVIDER", "="))
3519 COMPLETE_WITH("libc", "icu");
3520 else if (TailMatches("DETERMINISTIC", "="))
3521 COMPLETE_WITH("true", "false");
3522 }
3523
3524 /* CREATE DATABASE */
3525 else if (Matches("CREATE", "DATABASE", MatchAny))
3526 COMPLETE_WITH("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
3527 "IS_TEMPLATE", "STRATEGY",
3528 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
3529 "LC_COLLATE", "LC_CTYPE", "LOCALE", "OID",
3530 "LOCALE_PROVIDER", "ICU_LOCALE");
3531
3532 else if (Matches("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
3534 else if (Matches("CREATE", "DATABASE", MatchAny, "STRATEGY"))
3535 COMPLETE_WITH("WAL_LOG", "FILE_COPY");
3536
3537 /* CREATE DOMAIN */
3538 else if (Matches("CREATE", "DOMAIN", MatchAny))
3539 COMPLETE_WITH("AS");
3540 else if (Matches("CREATE", "DOMAIN", MatchAny, "AS"))
3542 else if (Matches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
3543 COMPLETE_WITH("COLLATE", "DEFAULT", "CONSTRAINT",
3544 "NOT NULL", "NULL", "CHECK (");
3545 else if (Matches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
3547
3548 /* CREATE EXTENSION */
3549 /* Complete with available extensions rather than installed ones. */
3550 else if (Matches("CREATE", "EXTENSION"))
3552 /* CREATE EXTENSION <name> */
3553 else if (Matches("CREATE", "EXTENSION", MatchAny))
3554 COMPLETE_WITH("WITH SCHEMA", "CASCADE", "VERSION");
3555 /* CREATE EXTENSION <name> VERSION */
3556 else if (Matches("CREATE", "EXTENSION", MatchAny, "VERSION"))
3557 {
3560 }
3561
3562 /* CREATE FOREIGN */
3563 else if (Matches("CREATE", "FOREIGN"))
3564 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3565
3566 /* CREATE FOREIGN DATA WRAPPER */
3567 else if (Matches("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
3568 COMPLETE_WITH("CONNECTION", "HANDLER", "OPTIONS", "VALIDATOR");
3569
3570 /* CREATE FOREIGN TABLE */
3571 else if (Matches("CREATE", "FOREIGN", "TABLE", MatchAny))
3572 COMPLETE_WITH("(", "PARTITION OF");
3573
3574 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
3575 /* First off we complete CREATE UNIQUE with "INDEX" */
3576 else if (TailMatches("CREATE", "UNIQUE"))
3577 COMPLETE_WITH("INDEX");
3578
3579 /*
3580 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
3581 * existing indexes
3582 */
3583 else if (TailMatches("CREATE|UNIQUE", "INDEX"))
3585 "ON", "CONCURRENTLY");
3586
3587 /*
3588 * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
3589 * that indexes can be created on
3590 */
3591 else if (TailMatches("INDEX|CONCURRENTLY", MatchAny, "ON") ||
3592 TailMatches("INDEX|CONCURRENTLY", "ON"))
3594
3595 /*
3596 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
3597 * indexes
3598 */
3599 else if (TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
3601 "ON");
3602 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
3603 else if (TailMatches("CREATE|UNIQUE", "INDEX", MatchAny) ||
3604 TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
3605 COMPLETE_WITH("ON");
3606
3607 /*
3608 * Complete INDEX <name> ON <table> with a list of table columns (which
3609 * should really be in parens)
3610 */
3611 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny) ||
3612 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny))
3613 COMPLETE_WITH("(", "USING");
3614 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny, "(") ||
3615 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
3617 /* same if you put in USING */
3618 else if (TailMatches("ON", MatchAny, "USING", MatchAny, "("))
3620 /* Complete USING with an index method */
3621 else if (TailMatches("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
3622 TailMatches("INDEX", MatchAny, "ON", MatchAny, "USING") ||
3623 TailMatches("INDEX", "ON", MatchAny, "USING"))
3625 else if (TailMatches("ON", MatchAny, "USING", MatchAny) &&
3628 COMPLETE_WITH("(");
3629
3630 /* CREATE OR REPLACE */
3631 else if (Matches("CREATE", "OR"))
3632 COMPLETE_WITH("REPLACE");
3633
3634 /* CREATE POLICY */
3635 /* Complete "CREATE POLICY <name> ON" */
3636 else if (Matches("CREATE", "POLICY", MatchAny))
3637 COMPLETE_WITH("ON");
3638 /* Complete "CREATE POLICY <name> ON <table>" */
3639 else if (Matches("CREATE", "POLICY", MatchAny, "ON"))
3641 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
3642 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny))
3643 COMPLETE_WITH("AS", "FOR", "TO", "USING (", "WITH CHECK (");
3644 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
3645 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
3646 COMPLETE_WITH("PERMISSIVE", "RESTRICTIVE");
3647
3648 /*
3649 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3650 * FOR|TO|USING|WITH CHECK
3651 */
3652 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
3653 COMPLETE_WITH("FOR", "TO", "USING", "WITH CHECK");
3654 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
3655 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
3656 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3657 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
3658 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
3659 COMPLETE_WITH("TO", "WITH CHECK (");
3660 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
3661 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
3662 COMPLETE_WITH("TO", "USING (");
3663 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
3664 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
3665 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3666 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
3667 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
3670 /* Complete "CREATE POLICY <name> ON <table> USING (" */
3671 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
3672 COMPLETE_WITH("(");
3673
3674 /*
3675 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3676 * ALL|SELECT|INSERT|UPDATE|DELETE
3677 */
3678 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
3679 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3680
3681 /*
3682 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3683 * INSERT TO|WITH CHECK"
3684 */
3685 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
3686 COMPLETE_WITH("TO", "WITH CHECK (");
3687
3688 /*
3689 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3690 * SELECT|DELETE TO|USING"
3691 */
3692 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
3693 COMPLETE_WITH("TO", "USING (");
3694
3695 /*
3696 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3697 * ALL|UPDATE TO|USING|WITH CHECK
3698 */
3699 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
3700 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3701
3702 /*
3703 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
3704 * <role>"
3705 */
3706 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
3709
3710 /*
3711 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3712 * USING ("
3713 */
3714 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
3715 COMPLETE_WITH("(");
3716
3717/* CREATE PROPERTY GRAPH */
3718 else if (Matches("CREATE", "PROPERTY"))
3719 COMPLETE_WITH("GRAPH");
3720 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny))
3721 COMPLETE_WITH("VERTEX");
3722 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE"))
3723 COMPLETE_WITH("TABLES");
3724 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES"))
3725 COMPLETE_WITH("(");
3726 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES", "("))
3728 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES", "(*)"))
3729 COMPLETE_WITH("EDGE");
3730 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP"))
3731 COMPLETE_WITH("TABLES");
3732 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP", "TABLES"))
3733 COMPLETE_WITH("(");
3734 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP", "TABLES", "("))
3736
3737/* CREATE PUBLICATION */
3738 else if (Matches("CREATE", "PUBLICATION", MatchAny))
3739 COMPLETE_WITH("FOR TABLE", "FOR TABLES IN SCHEMA", "FOR ALL TABLES", "FOR ALL SEQUENCES", "WITH (");
3740 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
3741 COMPLETE_WITH("TABLE", "TABLES IN SCHEMA", "ALL TABLES", "ALL SEQUENCES");
3742 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL"))
3743 COMPLETE_WITH("TABLES", "SEQUENCES");
3744 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
3745 COMPLETE_WITH("EXCEPT ( TABLE", "WITH (");
3746 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT"))
3747 COMPLETE_WITH("( TABLE");
3748 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "("))
3749 COMPLETE_WITH("TABLE");
3750 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE"))
3752 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd, ','))
3754 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd, ','))
3755 COMPLETE_WITH(")");
3756 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES"))
3757 COMPLETE_WITH("IN SCHEMA");
3758 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) && !ends_with(prev_wd, ','))
3759 COMPLETE_WITH("WHERE (", "WITH (");
3760 /* Complete "CREATE PUBLICATION <name> FOR TABLE" with "<table>, ..." */
3761 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE"))
3763
3764 /*
3765 * "CREATE PUBLICATION <name> FOR TABLE <name> WHERE (" - complete with
3766 * table attributes
3767 */
3768 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE"))
3769 COMPLETE_WITH("(");
3770 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "("))
3772 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "(*)"))
3773 COMPLETE_WITH(" WITH (");
3774
3775 /*
3776 * Complete "CREATE PUBLICATION <name> FOR TABLES IN SCHEMA <schema>, ..."
3777 */
3778 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA"))
3780 " AND nspname NOT LIKE E'pg\\\\_%%'",
3781 "CURRENT_SCHEMA");
3782 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA", MatchAny) && (!ends_with(prev_wd, ',')))
3783 COMPLETE_WITH("WITH (");
3784 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
3785 else if (Matches("CREATE", "PUBLICATION", MatchAnyN, "WITH", "("))
3786 COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root");
3787
3788/* CREATE RULE */
3789 /* Complete "CREATE [ OR REPLACE ] RULE <sth>" with "AS ON" */
3790 else if (Matches("CREATE", "RULE", MatchAny) ||
3791 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny))
3792 COMPLETE_WITH("AS ON");
3793 /* Complete "CREATE [ OR REPLACE ] RULE <sth> AS" with "ON" */
3794 else if (Matches("CREATE", "RULE", MatchAny, "AS") ||
3795 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS"))
3796 COMPLETE_WITH("ON");
3797
3798 /*
3799 * Complete "CREATE [ OR REPLACE ] RULE <sth> AS ON" with
3800 * SELECT|UPDATE|INSERT|DELETE
3801 */
3802 else if (Matches("CREATE", "RULE", MatchAny, "AS", "ON") ||
3803 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS", "ON"))
3804 COMPLETE_WITH("SELECT", "UPDATE", "INSERT", "DELETE");
3805 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
3806 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
3807 COMPLETE_WITH("TO");
3808 /* Complete "AS ON <sth> TO" with a table name */
3809 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
3811
3812/* CREATE SCHEMA [ <name> ] [ AUTHORIZATION ] */
3813 else if (Matches("CREATE", "SCHEMA"))
3815 "AUTHORIZATION");
3816 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION") ||
3817 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION"))
3820 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION", MatchAny) ||
3821 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION", MatchAny))
3822 COMPLETE_WITH("CREATE", "GRANT");
3823 else if (Matches("CREATE", "SCHEMA", MatchAny))
3824 COMPLETE_WITH("AUTHORIZATION", "CREATE", "GRANT");
3825
3826/* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3827 else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
3828 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
3829 COMPLETE_WITH("AS", "INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
3830 "CACHE", "CYCLE", "OWNED BY", "START WITH");
3831 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "AS") ||
3832 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "AS"))
3833 COMPLETE_WITH_CS("smallint", "integer", "bigint");
3834 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "NO") ||
3835 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
3836 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
3837
3838/* CREATE SERVER <name> */
3839 else if (Matches("CREATE", "SERVER", MatchAny))
3840 COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
3841
3842/* CREATE STATISTICS <name> */
3843 else if (Matches("CREATE", "STATISTICS", MatchAny))
3844 COMPLETE_WITH("(", "ON");
3845 else if (Matches("CREATE", "STATISTICS", MatchAny, "("))
3846 COMPLETE_WITH("ndistinct", "dependencies", "mcv");
3847 else if (Matches("CREATE", "STATISTICS", MatchAny, "(*)"))
3848 COMPLETE_WITH("ON");
3849 else if (Matches("CREATE", "STATISTICS", MatchAny, MatchAnyN, "FROM"))
3851
3852/* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3853 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
3854 else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
3855 COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW");
3856 /* Complete "CREATE UNLOGGED" with TABLE or SEQUENCE */
3857 else if (TailMatches("CREATE", "UNLOGGED"))
3858 COMPLETE_WITH("TABLE", "SEQUENCE");
3859 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
3860 else if (TailMatches("PARTITION", "BY"))
3861 COMPLETE_WITH("RANGE (", "LIST (", "HASH (");
3862 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
3863 else if (TailMatches("PARTITION", "OF"))
3865 /* Limited completion support for partition bound specification */
3866 else if (TailMatches("PARTITION", "OF", MatchAny))
3867 COMPLETE_WITH("FOR VALUES", "DEFAULT");
3868 /* Complete CREATE TABLE <name> with '(', AS, OF or PARTITION OF */
3869 else if (TailMatches("CREATE", "TABLE", MatchAny) ||
3870 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny))
3871 COMPLETE_WITH("(", "AS", "OF", "PARTITION OF");
3872 /* Complete CREATE TABLE <name> OF with list of composite types */
3873 else if (TailMatches("CREATE", "TABLE", MatchAny, "OF") ||
3874 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "OF"))
3876 /* Complete CREATE TABLE <name> [ (...) ] AS with list of keywords */
3877 else if (TailMatches("CREATE", "TABLE", MatchAny, "AS") ||
3878 TailMatches("CREATE", "TABLE", MatchAny, "(*)", "AS") ||
3879 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "AS") ||
3880 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "AS"))
3881 COMPLETE_WITH("EXECUTE", "SELECT", "TABLE", "VALUES", "WITH");
3882 /* Complete CREATE TABLE name (...) with supported options */
3883 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)"))
3884 COMPLETE_WITH("AS", "INHERITS (", "PARTITION BY", "USING", "TABLESPACE", "WITH (");
3885 else if (TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)"))
3886 COMPLETE_WITH("AS", "INHERITS (", "USING", "TABLESPACE", "WITH (");
3887 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)"))
3888 COMPLETE_WITH("AS", "INHERITS (", "ON COMMIT", "PARTITION BY", "USING",
3889 "TABLESPACE", "WITH (");
3890 /* Complete CREATE TABLE (...) USING with table access methods */
3891 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "USING") ||
3892 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "USING"))
3894 /* Complete CREATE TABLE (...) WITH with storage parameters */
3895 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "WITH", "(") ||
3896 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "WITH", "("))
3898 /* Complete CREATE TABLE ON COMMIT with actions */
3899 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)", "ON", "COMMIT"))
3900 COMPLETE_WITH("DELETE ROWS", "DROP", "PRESERVE ROWS");
3901
3902/* CREATE TABLESPACE */
3903 else if (Matches("CREATE", "TABLESPACE", MatchAny))
3904 COMPLETE_WITH("OWNER", "LOCATION");
3905 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
3906 else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
3907 COMPLETE_WITH("LOCATION");
3908
3909/* CREATE TEXT SEARCH */
3910 else if (Matches("CREATE", "TEXT", "SEARCH"))
3911 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3912 else if (Matches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
3913 COMPLETE_WITH("(");
3914
3915/* CREATE TRANSFORM */
3916 else if (Matches("CREATE", "TRANSFORM") ||
3917 Matches("CREATE", "OR", "REPLACE", "TRANSFORM"))
3918 COMPLETE_WITH("FOR");
3919 else if (Matches("CREATE", "TRANSFORM", "FOR") ||
3920 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR"))
3922 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny) ||
3923 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny))
3924 COMPLETE_WITH("LANGUAGE");
3925 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE") ||
3926 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3927 {
3930 }
3931
3932/* CREATE SUBSCRIPTION */
3933 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny))
3934 COMPLETE_WITH("CONNECTION", "SERVER");
3935 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER"))
3937 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER", MatchAny))
3938 COMPLETE_WITH("PUBLICATION");
3939 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
3940 COMPLETE_WITH("PUBLICATION");
3941 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER",
3942 MatchAny, "PUBLICATION"))
3943 {
3944 /* complete with nothing here as this refers to remote publications */
3945 }
3946 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
3947 MatchAny, "PUBLICATION"))
3948 {
3949 /* complete with nothing here as this refers to remote publications */
3950 }
3951 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "PUBLICATION", MatchAny))
3952 COMPLETE_WITH("WITH (");
3953 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
3954 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "WITH", "("))
3955 COMPLETE_WITH("binary", "connect", "copy_data", "create_slot",
3956 "disable_on_error", "enabled", "failover",
3957 "max_retention_duration", "origin",
3958 "password_required", "retain_dead_tuples",
3959 "run_as_owner", "slot_name", "streaming",
3960 "synchronous_commit", "two_phase");
3961
3962/* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
3963
3964 /*
3965 * Complete CREATE [ OR REPLACE ] TRIGGER <name> with BEFORE|AFTER|INSTEAD
3966 * OF.
3967 */
3968 else if (TailMatches("CREATE", "TRIGGER", MatchAny) ||
3969 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny))
3970 COMPLETE_WITH("BEFORE", "AFTER", "INSTEAD OF");
3971
3972 /*
3973 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER with an
3974 * event.
3975 */
3976 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER") ||
3977 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
3978 COMPLETE_WITH("INSERT", "DELETE", "UPDATE", "TRUNCATE");
3979 /* Complete CREATE [ OR REPLACE ] TRIGGER <name> INSTEAD OF with an event */
3980 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF") ||
3981 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
3982 COMPLETE_WITH("INSERT", "DELETE", "UPDATE");
3983
3984 /*
3985 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER sth with
3986 * OR|ON.
3987 */
3988 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3989 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3990 TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny) ||
3991 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
3992 COMPLETE_WITH("ON", "OR");
3993
3994 /*
3995 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER event ON
3996 * with a list of tables. EXECUTE FUNCTION is the recommended grammar
3997 * instead of EXECUTE PROCEDURE in version 11 and upwards.
3998 */
3999 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON") ||
4000 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
4002
4003 /*
4004 * Complete CREATE [ OR REPLACE ] TRIGGER ... INSTEAD OF event ON with a
4005 * list of views.
4006 */
4007 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON") ||
4008 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
4010 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4011 "ON", MatchAny) ||
4012 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4013 "ON", MatchAny))
4014 {
4015 if (pset.sversion >= 110000)
4016 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
4017 "REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
4018 else
4019 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
4020 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4021 }
4022 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4023 "DEFERRABLE") ||
4024 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4025 "DEFERRABLE") ||
4026 Matches("CREATE", "TRIGGER", MatchAnyN,
4027 "INITIALLY", "IMMEDIATE|DEFERRED") ||
4028 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4029 "INITIALLY", "IMMEDIATE|DEFERRED"))
4030 {
4031 if (pset.sversion >= 110000)
4032 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
4033 else
4034 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4035 }
4036 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4037 "REFERENCING") ||
4038 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4039 "REFERENCING"))
4040 COMPLETE_WITH("OLD TABLE", "NEW TABLE");
4041 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4042 "OLD|NEW", "TABLE") ||
4043 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4044 "OLD|NEW", "TABLE"))
4045 COMPLETE_WITH("AS");
4046 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4047 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
4048 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4049 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
4050 Matches("CREATE", "TRIGGER", MatchAnyN,
4051 "REFERENCING", "OLD", "TABLE", MatchAny) ||
4052 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4053 "REFERENCING", "OLD", "TABLE", MatchAny))
4054 {
4055 if (pset.sversion >= 110000)
4056 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
4057 else
4058 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4059 }
4060 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4061 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
4062 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4063 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
4064 Matches("CREATE", "TRIGGER", MatchAnyN,
4065 "REFERENCING", "NEW", "TABLE", MatchAny) ||
4066 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4067 "REFERENCING", "NEW", "TABLE", MatchAny))
4068 {
4069 if (pset.sversion >= 110000)
4070 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
4071 else
4072 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4073 }
4074 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4075 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4076 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4077 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4078 Matches("CREATE", "TRIGGER", MatchAnyN,
4079 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4080 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4081 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4082 Matches("CREATE", "TRIGGER", MatchAnyN,
4083 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4084 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4085 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4086 Matches("CREATE", "TRIGGER", MatchAnyN,
4087 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4088 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4089 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny))
4090 {
4091 if (pset.sversion >= 110000)
4092 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE FUNCTION");
4093 else
4094 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE PROCEDURE");
4095 }
4096 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4097 "FOR") ||
4098 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4099 "FOR"))
4100 COMPLETE_WITH("EACH", "ROW", "STATEMENT");
4101 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4102 "FOR", "EACH") ||
4103 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4104 "FOR", "EACH"))
4105 COMPLETE_WITH("ROW", "STATEMENT");
4106 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4107 "FOR", "EACH", "ROW|STATEMENT") ||
4108 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4109 "FOR", "EACH", "ROW|STATEMENT") ||
4110 Matches("CREATE", "TRIGGER", MatchAnyN,
4111 "FOR", "ROW|STATEMENT") ||
4112 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4113 "FOR", "ROW|STATEMENT"))
4114 {
4115 if (pset.sversion >= 110000)
4116 COMPLETE_WITH("WHEN (", "EXECUTE FUNCTION");
4117 else
4118 COMPLETE_WITH("WHEN (", "EXECUTE PROCEDURE");
4119 }
4120 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4121 "WHEN", "(*)") ||
4122 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4123 "WHEN", "(*)"))
4124 {
4125 if (pset.sversion >= 110000)
4126 COMPLETE_WITH("EXECUTE FUNCTION");
4127 else
4128 COMPLETE_WITH("EXECUTE PROCEDURE");
4129 }
4130
4131 /*
4132 * Complete CREATE [ OR REPLACE ] TRIGGER ... EXECUTE with
4133 * PROCEDURE|FUNCTION.
4134 */
4135 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4136 "EXECUTE") ||
4137 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4138 "EXECUTE"))
4139 {
4140 if (pset.sversion >= 110000)
4141 COMPLETE_WITH("FUNCTION");
4142 else
4143 COMPLETE_WITH("PROCEDURE");
4144 }
4145 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4146 "EXECUTE", "FUNCTION|PROCEDURE") ||
4147 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4148 "EXECUTE", "FUNCTION|PROCEDURE"))
4150
4151/* CREATE ROLE,USER,GROUP <name> */
4152 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny) &&
4153 !TailMatches("USER", "MAPPING"))
4154 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
4155 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
4156 "LOGIN", "NOBYPASSRLS",
4157 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
4158 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
4159 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
4160 "VALID UNTIL", "WITH");
4161
4162/* CREATE ROLE,USER,GROUP <name> WITH */
4163 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
4164 /* Similar to the above, but don't complete "WITH" again. */
4165 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
4166 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
4167 "LOGIN", "NOBYPASSRLS",
4168 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
4169 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
4170 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
4171 "VALID UNTIL");
4172
4173 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
4174 else if (Matches("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
4175 COMPLETE_WITH("GROUP", "ROLE");
4176
4177/* CREATE TYPE */
4178 else if (Matches("CREATE", "TYPE", MatchAny))
4179 COMPLETE_WITH("(", "AS");
4180 else if (Matches("CREATE", "TYPE", MatchAny, "AS"))
4181 COMPLETE_WITH("ENUM", "RANGE", "(");
4182 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "("))
4183 {
4184 if (TailMatches("(|*,", MatchAny))
4186 else if (TailMatches("(|*,", MatchAny, MatchAnyExcept("*)")))
4187 COMPLETE_WITH("COLLATE", ",", ")");
4188 }
4189 else if (Matches("CREATE", "TYPE", MatchAny, "AS", "ENUM|RANGE"))
4190 COMPLETE_WITH("(");
4191 else if (HeadMatches("CREATE", "TYPE", MatchAny, "("))
4192 {
4193 if (TailMatches("(|*,"))
4194 COMPLETE_WITH("INPUT", "OUTPUT", "RECEIVE", "SEND",
4195 "TYPMOD_IN", "TYPMOD_OUT", "ANALYZE", "SUBSCRIPT",
4196 "INTERNALLENGTH", "PASSEDBYVALUE", "ALIGNMENT",
4197 "STORAGE", "LIKE", "CATEGORY", "PREFERRED",
4198 "DEFAULT", "ELEMENT", "DELIMITER",
4199 "COLLATABLE");
4200 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
4201 COMPLETE_WITH("=");
4202 else if (TailMatches("=", MatchAnyExcept("*)")))
4203 COMPLETE_WITH(",", ")");
4204 }
4205 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "RANGE", "("))
4206 {
4207 if (TailMatches("(|*,"))
4208 COMPLETE_WITH("SUBTYPE", "SUBTYPE_OPCLASS", "COLLATION",
4209 "CANONICAL", "SUBTYPE_DIFF",
4210 "MULTIRANGE_TYPE_NAME");
4211 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
4212 COMPLETE_WITH("=");
4213 else if (TailMatches("=", MatchAnyExcept("*)")))
4214 COMPLETE_WITH(",", ")");
4215 }
4216
4217/* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
4218 /* Complete CREATE [ OR REPLACE ] VIEW <name> with AS or WITH */
4219 else if (TailMatches("CREATE", "VIEW", MatchAny) ||
4220 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny))
4221 COMPLETE_WITH("AS", "WITH");
4222 /* Complete "CREATE [ OR REPLACE ] VIEW <sth> AS with "SELECT" */
4223 else if (TailMatches("CREATE", "VIEW", MatchAny, "AS") ||
4224 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "AS"))
4225 COMPLETE_WITH("SELECT");
4226 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( yyy [= zzz] ) */
4227 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH") ||
4228 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH"))
4229 COMPLETE_WITH("(");
4230 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(") ||
4231 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "("))
4233 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option") ||
4234 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option"))
4235 COMPLETE_WITH("=");
4236 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option", "=") ||
4237 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option", "="))
4238 COMPLETE_WITH("local", "cascaded");
4239 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS */
4240 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)") ||
4241 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)"))
4242 COMPLETE_WITH("AS");
4243 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS SELECT */
4244 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)", "AS") ||
4245 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)", "AS"))
4246 COMPLETE_WITH("SELECT");
4247
4248/* CREATE MATERIALIZED VIEW */
4249 else if (Matches("CREATE", "MATERIALIZED"))
4250 COMPLETE_WITH("VIEW");
4251 /* Complete CREATE MATERIALIZED VIEW <name> with AS or USING */
4252 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
4253 COMPLETE_WITH("AS", "USING");
4254
4255 /*
4256 * Complete CREATE MATERIALIZED VIEW <name> USING with list of access
4257 * methods
4258 */
4259 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING"))
4261 /* Complete CREATE MATERIALIZED VIEW <name> USING <access method> with AS */
4262 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny))
4263 COMPLETE_WITH("AS");
4264
4265 /*
4266 * Complete CREATE MATERIALIZED VIEW <name> [USING <access method> ] AS
4267 * with "SELECT"
4268 */
4269 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS") ||
4270 Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS"))
4271 COMPLETE_WITH("SELECT");
4272
4273/* CREATE EVENT TRIGGER */
4274 else if (Matches("CREATE", "EVENT"))
4275 COMPLETE_WITH("TRIGGER");
4276 /* Complete CREATE EVENT TRIGGER <name> with ON */
4277 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny))
4278 COMPLETE_WITH("ON");
4279 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
4280 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
4281 COMPLETE_WITH("ddl_command_start", "ddl_command_end", "login",
4282 "sql_drop", "table_rewrite");
4283
4284 /*
4285 * Complete CREATE EVENT TRIGGER <name> ON <event_type>. EXECUTE FUNCTION
4286 * is the recommended grammar instead of EXECUTE PROCEDURE in version 11
4287 * and upwards.
4288 */
4289 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON", MatchAny))
4290 {
4291 if (pset.sversion >= 110000)
4292 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE FUNCTION");
4293 else
4294 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE PROCEDURE");
4295 }
4296 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "WHEN|AND", MatchAny, "IN", "(*)"))
4297 {
4298 if (pset.sversion >= 110000)
4299 COMPLETE_WITH("EXECUTE FUNCTION");
4300 else
4301 COMPLETE_WITH("EXECUTE PROCEDURE");
4302 }
4303 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "EXECUTE", "FUNCTION|PROCEDURE"))
4305
4306/* DEALLOCATE */
4307 else if (Matches("DEALLOCATE"))
4309 "ALL");
4310
4311/* DECLARE */
4312
4313 /*
4314 * Complete DECLARE <name> with one of BINARY, ASENSITIVE, INSENSITIVE,
4315 * SCROLL, NO SCROLL, and CURSOR.
4316 */
4317 else if (Matches("DECLARE", MatchAny))
4318 COMPLETE_WITH("BINARY", "ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL",
4319 "CURSOR");
4320
4321 /*
4322 * Complete DECLARE ... <option> with other options. The PostgreSQL parser
4323 * allows DECLARE options to be specified in any order. But the
4324 * tab-completion follows the ordering of them that the SQL standard
4325 * provides, like the syntax of DECLARE command in the documentation
4326 * indicates.
4327 */
4328 else if (Matches("DECLARE", MatchAnyN, "BINARY"))
4329 COMPLETE_WITH("ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR");
4330 else if (Matches("DECLARE", MatchAnyN, "ASENSITIVE|INSENSITIVE"))
4331 COMPLETE_WITH("SCROLL", "NO SCROLL", "CURSOR");
4332 else if (Matches("DECLARE", MatchAnyN, "SCROLL"))
4333 COMPLETE_WITH("CURSOR");
4334 /* Complete DECLARE ... [options] NO with SCROLL */
4335 else if (Matches("DECLARE", MatchAnyN, "NO"))
4336 COMPLETE_WITH("SCROLL");
4337
4338 /*
4339 * Complete DECLARE ... CURSOR with one of WITH HOLD, WITHOUT HOLD, and
4340 * FOR
4341 */
4342 else if (Matches("DECLARE", MatchAnyN, "CURSOR"))
4343 COMPLETE_WITH("WITH HOLD", "WITHOUT HOLD", "FOR");
4344 /* Complete DECLARE ... CURSOR WITH|WITHOUT with HOLD */
4345 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT"))
4346 COMPLETE_WITH("HOLD");
4347 /* Complete DECLARE ... CURSOR WITH|WITHOUT HOLD with FOR */
4348 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT", "HOLD"))
4349 COMPLETE_WITH("FOR");
4350
4351/* DELETE --- can be inside EXPLAIN, RULE, etc */
4352 /* Complete DELETE with "FROM" */
4353 else if (Matches("DELETE"))
4354 COMPLETE_WITH("FROM");
4355 /* Complete DELETE FROM with a list of tables */
4356 else if (TailMatches("DELETE", "FROM"))
4358 /* Complete DELETE FROM <table> */
4359 else if (TailMatches("DELETE", "FROM", MatchAny))
4360 COMPLETE_WITH("USING", "WHERE");
4361 /* Complete DELETE FROM <table> USING with relations supporting SELECT */
4362 else if (TailMatches("DELETE", "FROM", MatchAny, "USING"))
4364
4365/* DISCARD */
4366 else if (Matches("DISCARD"))
4367 COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP");
4368
4369/* DO */
4370 else if (Matches("DO"))
4371 COMPLETE_WITH("LANGUAGE");
4372
4373/* DROP */
4374 /* Complete DROP object with CASCADE / RESTRICT */
4375 else if (Matches("DROP",
4376 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
4377 MatchAny) ||
4378 Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
4379 Matches("DROP", "EVENT", "TRIGGER", MatchAny) ||
4380 Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4381 Matches("DROP", "FOREIGN", "TABLE", MatchAny) ||
4382 Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
4383 COMPLETE_WITH("CASCADE", "RESTRICT");
4384 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
4385 ends_with(prev_wd, ')'))
4386 COMPLETE_WITH("CASCADE", "RESTRICT");
4387
4388 /* help completing some of the variants */
4389 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
4390 COMPLETE_WITH("(");
4391 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
4393 else if (Matches("DROP", "FOREIGN"))
4394 COMPLETE_WITH("DATA WRAPPER", "TABLE");
4395 else if (Matches("DROP", "DATABASE", MatchAny))
4396 COMPLETE_WITH("WITH (");
4397 else if (HeadMatches("DROP", "DATABASE") && (ends_with(prev_wd, '(')))
4398 COMPLETE_WITH("FORCE");
4399
4400 /* DROP INDEX */
4401 else if (Matches("DROP", "INDEX"))
4403 "CONCURRENTLY");
4404 else if (Matches("DROP", "INDEX", "CONCURRENTLY"))
4406 else if (Matches("DROP", "INDEX", MatchAny))
4407 COMPLETE_WITH("CASCADE", "RESTRICT");
4408 else if (Matches("DROP", "INDEX", "CONCURRENTLY", MatchAny))
4409 COMPLETE_WITH("CASCADE", "RESTRICT");
4410
4411 /* DROP MATERIALIZED VIEW */
4412 else if (Matches("DROP", "MATERIALIZED"))
4413 COMPLETE_WITH("VIEW");
4414 else if (Matches("DROP", "MATERIALIZED", "VIEW"))
4416 else if (Matches("DROP", "MATERIALIZED", "VIEW", MatchAny))
4417 COMPLETE_WITH("CASCADE", "RESTRICT");
4418
4419 /* DROP OWNED BY */
4420 else if (Matches("DROP", "OWNED"))
4421 COMPLETE_WITH("BY");
4422 else if (Matches("DROP", "OWNED", "BY"))
4424 else if (Matches("DROP", "OWNED", "BY", MatchAny))
4425 COMPLETE_WITH("CASCADE", "RESTRICT");
4426
4427 /* DROP TEXT SEARCH */
4428 else if (Matches("DROP", "TEXT", "SEARCH"))
4429 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
4430
4431 /* DROP TRIGGER */
4432 else if (Matches("DROP", "TRIGGER", MatchAny))
4433 COMPLETE_WITH("ON");
4434 else if (Matches("DROP", "TRIGGER", MatchAny, "ON"))
4435 {
4438 }
4439 else if (Matches("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
4440 COMPLETE_WITH("CASCADE", "RESTRICT");
4441
4442 /* DROP ACCESS METHOD */
4443 else if (Matches("DROP", "ACCESS"))
4444 COMPLETE_WITH("METHOD");
4445 else if (Matches("DROP", "ACCESS", "METHOD"))
4447
4448 /* DROP EVENT TRIGGER */
4449 else if (Matches("DROP", "EVENT"))
4450 COMPLETE_WITH("TRIGGER");
4451 else if (Matches("DROP", "EVENT", "TRIGGER"))
4453
4454 /* DROP POLICY <name> */
4455 else if (Matches("DROP", "POLICY"))
4457 /* DROP POLICY <name> ON */
4458 else if (Matches("DROP", "POLICY", MatchAny))
4459 COMPLETE_WITH("ON");
4460 /* DROP POLICY <name> ON <table> */
4461 else if (Matches("DROP", "POLICY", MatchAny, "ON"))
4462 {
4465 }
4466 else if (Matches("DROP", "POLICY", MatchAny, "ON", MatchAny))
4467 COMPLETE_WITH("CASCADE", "RESTRICT");
4468
4469 /* DROP PROPERTY GRAPH */
4470 else if (Matches("DROP", "PROPERTY"))
4471 COMPLETE_WITH("GRAPH");
4472 else if (Matches("DROP", "PROPERTY", "GRAPH"))
4474
4475 /* DROP RULE */
4476 else if (Matches("DROP", "RULE", MatchAny))
4477 COMPLETE_WITH("ON");
4478 else if (Matches("DROP", "RULE", MatchAny, "ON"))
4479 {
4482 }
4483 else if (Matches("DROP", "RULE", MatchAny, "ON", MatchAny))
4484 COMPLETE_WITH("CASCADE", "RESTRICT");
4485
4486 /* DROP TRANSFORM */
4487 else if (Matches("DROP", "TRANSFORM"))
4488 COMPLETE_WITH("FOR");
4489 else if (Matches("DROP", "TRANSFORM", "FOR"))
4491 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny))
4492 COMPLETE_WITH("LANGUAGE");
4493 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
4494 {
4497 }
4498 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE", MatchAny))
4499 COMPLETE_WITH("CASCADE", "RESTRICT");
4500
4501/* EXECUTE */
4502 else if (Matches("EXECUTE"))
4504
4505/*
4506 * EXPLAIN [ ( option [, ...] ) ] statement
4507 * EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
4508 */
4509 else if (Matches("EXPLAIN"))
4510 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4511 "MERGE INTO", "EXECUTE", "ANALYZE", "VERBOSE");
4512 else if (HeadMatches("EXPLAIN", "(*") &&
4513 !HeadMatches("EXPLAIN", "(*)"))
4514 {
4515 /*
4516 * This fires if we're in an unfinished parenthesized option list.
4517 * get_previous_words treats a completed parenthesized option list as
4518 * one word, so the above test is correct.
4519 */
4520 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
4521 COMPLETE_WITH("ANALYZE", "VERBOSE", "COSTS", "SETTINGS", "GENERIC_PLAN",
4522 "BUFFERS", "SERIALIZE", "WAL", "TIMING", "SUMMARY",
4523 "MEMORY", "FORMAT");
4524 else if (TailMatches("ANALYZE|VERBOSE|COSTS|SETTINGS|GENERIC_PLAN|BUFFERS|WAL|TIMING|SUMMARY|MEMORY"))
4525 COMPLETE_WITH("ON", "OFF");
4526 else if (TailMatches("SERIALIZE"))
4527 COMPLETE_WITH("TEXT", "NONE", "BINARY");
4528 else if (TailMatches("FORMAT"))
4529 COMPLETE_WITH("TEXT", "XML", "JSON", "YAML");
4530 }
4531 else if (Matches("EXPLAIN", "ANALYZE"))
4532 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4533 "MERGE INTO", "EXECUTE", "VERBOSE");
4534 else if (Matches("EXPLAIN", "(*)") ||
4535 Matches("EXPLAIN", "VERBOSE") ||
4536 Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
4537 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4538 "MERGE INTO", "EXECUTE");
4539
4540/* FETCH && MOVE */
4541
4542 /*
4543 * Complete FETCH with one of ABSOLUTE, BACKWARD, FORWARD, RELATIVE, ALL,
4544 * NEXT, PRIOR, FIRST, LAST, FROM, IN, and a list of cursors
4545 */
4546 else if (Matches("FETCH|MOVE"))
4548 "ABSOLUTE",
4549 "BACKWARD",
4550 "FORWARD",
4551 "RELATIVE",
4552 "ALL",
4553 "NEXT",
4554 "PRIOR",
4555 "FIRST",
4556 "LAST",
4557 "FROM",
4558 "IN");
4559
4560 /*
4561 * Complete FETCH BACKWARD or FORWARD with one of ALL, FROM, IN, and a
4562 * list of cursors
4563 */
4564 else if (Matches("FETCH|MOVE", "BACKWARD|FORWARD"))
4566 "ALL",
4567 "FROM",
4568 "IN");
4569
4570 /*
4571 * Complete FETCH <direction> with "FROM" or "IN". These are equivalent,
4572 * but we may as well tab-complete both: perhaps some users prefer one
4573 * variant or the other.
4574 */
4575 else if (Matches("FETCH|MOVE", "ABSOLUTE|BACKWARD|FORWARD|RELATIVE",
4576 MatchAnyExcept("FROM|IN")) ||
4577 Matches("FETCH|MOVE", "ALL|NEXT|PRIOR|FIRST|LAST"))
4579 "FROM",
4580 "IN");
4581 /* Complete FETCH <direction> "FROM" or "IN" with a list of cursors */
4582 else if (Matches("FETCH|MOVE", MatchAnyN, "FROM|IN"))
4584
4585/* FOREIGN DATA WRAPPER */
4586 /* applies in ALTER/DROP FDW and in CREATE SERVER */
4587 else if (TailMatches("FOREIGN", "DATA", "WRAPPER") &&
4588 !TailMatches("CREATE", MatchAny, MatchAny, MatchAny))
4590 /* applies in CREATE SERVER */
4591 else if (Matches("CREATE", "SERVER", MatchAnyN, "FOREIGN", "DATA", "WRAPPER", MatchAny))
4592 COMPLETE_WITH("OPTIONS");
4593
4594/* FOREIGN TABLE */
4595 else if (TailMatches("FOREIGN", "TABLE") &&
4596 !TailMatches("CREATE", MatchAny, MatchAny))
4598
4599/* FOREIGN SERVER */
4600 else if (TailMatches("FOREIGN", "SERVER"))
4602
4603/*
4604 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
4605 * ALTER DEFAULT PRIVILEGES, so use TailMatches
4606 */
4607 /* Complete GRANT/REVOKE with a list of roles and privileges */
4608 else if (TailMatches("GRANT|REVOKE") ||
4609 TailMatches("REVOKE", "ADMIN|GRANT|INHERIT|SET", "OPTION", "FOR"))
4610 {
4611 /*
4612 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
4613 * privileges (can't grant roles)
4614 */
4615 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4616 {
4617 if (TailMatches("GRANT") ||
4618 TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4619 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4620 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4621 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL");
4622 else if (TailMatches("REVOKE"))
4623 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4624 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4625 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL",
4626 "GRANT OPTION FOR");
4627 }
4628 else if (TailMatches("GRANT"))
4631 else if (TailMatches("REVOKE"))
4634 "GRANT OPTION FOR",
4635 "ADMIN OPTION FOR",
4636 "INHERIT OPTION FOR",
4637 "SET OPTION FOR");
4638 else if (TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4640 else if (TailMatches("REVOKE", "ADMIN|INHERIT|SET", "OPTION", "FOR"))
4642 }
4643
4644 else if (TailMatches("GRANT|REVOKE", "ALTER") ||
4645 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER"))
4646 COMPLETE_WITH("SYSTEM");
4647
4648 else if (TailMatches("REVOKE", "SET"))
4649 COMPLETE_WITH("ON PARAMETER", "OPTION FOR");
4650 else if (TailMatches("GRANT", "SET") ||
4651 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "SET") ||
4652 TailMatches("GRANT|REVOKE", "ALTER", "SYSTEM") ||
4653 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER", "SYSTEM"))
4654 COMPLETE_WITH("ON PARAMETER");
4655
4656 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "PARAMETER") ||
4657 TailMatches("GRANT|REVOKE", MatchAny, MatchAny, "ON", "PARAMETER") ||
4658 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER") ||
4659 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER"))
4661
4662 else if (TailMatches("GRANT", MatchAny, "ON", "PARAMETER", MatchAny) ||
4663 TailMatches("GRANT", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4664 COMPLETE_WITH("TO");
4665
4666 else if (TailMatches("REVOKE", MatchAny, "ON", "PARAMETER", MatchAny) ||
4667 TailMatches("REVOKE", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny) ||
4668 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER", MatchAny) ||
4669 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4670 COMPLETE_WITH("FROM");
4671
4672 /*
4673 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
4674 * TO/FROM
4675 */
4676 else if (TailMatches("GRANT|REVOKE", MatchAny) ||
4677 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny))
4678 {
4679 if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|MAINTAIN|ALL"))
4680 COMPLETE_WITH("ON");
4681 else if (TailMatches("GRANT", MatchAny))
4682 COMPLETE_WITH("TO");
4683 else
4684 COMPLETE_WITH("FROM");
4685 }
4686
4687 /*
4688 * Complete GRANT/REVOKE <sth> ON with a list of appropriate relations.
4689 *
4690 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
4691 * here will only work if the privilege list contains exactly one
4692 * privilege.
4693 */
4694 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON") ||
4695 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON"))
4696 {
4697 /*
4698 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
4699 * objects supported.
4700 */
4701 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4702 COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS", "LARGE OBJECTS");
4703 else
4705 "ALL FUNCTIONS IN SCHEMA",
4706 "ALL PROCEDURES IN SCHEMA",
4707 "ALL ROUTINES IN SCHEMA",
4708 "ALL SEQUENCES IN SCHEMA",
4709 "ALL TABLES IN SCHEMA",
4710 "DATABASE",
4711 "DOMAIN",
4712 "FOREIGN DATA WRAPPER",
4713 "FOREIGN SERVER",
4714 "FUNCTION",
4715 "LANGUAGE",
4716 "LARGE OBJECT",
4717 "PARAMETER",
4718 "PROCEDURE",
4719 "PROPERTY GRAPH",
4720 "ROUTINE",
4721 "SCHEMA",
4722 "SEQUENCE",
4723 "TABLE",
4724 "TABLESPACE",
4725 "TYPE");
4726 }
4727 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
4728 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
4729 COMPLETE_WITH("FUNCTIONS IN SCHEMA",
4730 "PROCEDURES IN SCHEMA",
4731 "ROUTINES IN SCHEMA",
4732 "SEQUENCES IN SCHEMA",
4733 "TABLES IN SCHEMA");
4734
4735 /*
4736 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
4737 * appropriate objects or keywords.
4738 *
4739 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
4740 */
4741 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny) ||
4742 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny))
4743 {
4744 if (TailMatches("DATABASE"))
4746 else if (TailMatches("DOMAIN"))
4748 else if (TailMatches("FUNCTION"))
4750 else if (TailMatches("FOREIGN"))
4751 COMPLETE_WITH("DATA WRAPPER", "SERVER");
4752 else if (TailMatches("LANGUAGE"))
4754 else if (TailMatches("LARGE"))
4755 {
4756 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4757 COMPLETE_WITH("OBJECTS");
4758 else
4759 COMPLETE_WITH("OBJECT");
4760 }
4761 else if (TailMatches("PROCEDURE"))
4763 else if (TailMatches("ROUTINE"))
4765 else if (TailMatches("SCHEMA"))
4767 else if (TailMatches("SEQUENCE"))
4769 else if (TailMatches("TABLE"))
4771 else if (TailMatches("TABLESPACE"))
4773 else if (TailMatches("TYPE"))
4775 else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
4776 COMPLETE_WITH("TO");
4777 else
4778 COMPLETE_WITH("FROM");
4779 }
4780
4781 /*
4782 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
4783 * CURRENT_ROLE, CURRENT_USER, or SESSION_USER.
4784 */
4785 else if (Matches("GRANT", MatchAnyN, "TO") ||
4786 Matches("REVOKE", MatchAnyN, "FROM"))
4789
4790 /*
4791 * Offer grant options after that.
4792 */
4793 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny))
4794 COMPLETE_WITH("WITH ADMIN",
4795 "WITH INHERIT",
4796 "WITH SET",
4797 "WITH GRANT OPTION",
4798 "GRANTED BY");
4799 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH"))
4800 COMPLETE_WITH("ADMIN",
4801 "INHERIT",
4802 "SET",
4803 "GRANT OPTION");
4804 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", "ADMIN|INHERIT|SET"))
4805 COMPLETE_WITH("OPTION", "TRUE", "FALSE");
4806 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION"))
4807 COMPLETE_WITH("GRANTED BY");
4808 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY"))
4811 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
4812 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO|FROM"))
4815 /* Offer WITH GRANT OPTION after that */
4816 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO", MatchAny))
4817 COMPLETE_WITH("WITH GRANT OPTION");
4818 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
4819 else if (Matches("GRANT|REVOKE", MatchAnyN, "ON", MatchAny, MatchAny) &&
4820 !TailMatches("FOREIGN", "SERVER") && !TailMatches("LARGE", "OBJECT"))
4821 {
4822 if (Matches("GRANT", MatchAnyN, "ON", MatchAny, MatchAny))
4823 COMPLETE_WITH("TO");
4824 else
4825 COMPLETE_WITH("FROM");
4826 }
4827
4828 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
4829 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
4830 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
4831 {
4833 COMPLETE_WITH("TO");
4834 else
4835 COMPLETE_WITH("FROM");
4836 }
4837
4838 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
4839 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4840 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
4841 {
4843 COMPLETE_WITH("TO");
4844 else
4845 COMPLETE_WITH("FROM");
4846 }
4847
4848 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
4849 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
4850 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
4851 {
4853 COMPLETE_WITH("TO");
4854 else
4855 COMPLETE_WITH("FROM");
4856 }
4857
4858 /* Complete "GRANT/REVOKE * ON LARGE OBJECT *" with TO/FROM */
4859 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "LARGE", "OBJECT", MatchAny) ||
4860 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "LARGE", "OBJECT", MatchAny))
4861 {
4863 COMPLETE_WITH("TO");
4864 else
4865 COMPLETE_WITH("FROM");
4866 }
4867
4868 /* Complete "GRANT/REVOKE * ON LARGE OBJECTS" with TO/FROM */
4869 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "LARGE", "OBJECTS") ||
4870 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "LARGE", "OBJECTS"))
4871 {
4873 COMPLETE_WITH("TO");
4874 else
4875 COMPLETE_WITH("FROM");
4876 }
4877
4878/* GRAPH_TABLE */
4879 else if (TailMatches("GRAPH_TABLE"))
4880 COMPLETE_WITH("(");
4881 else if (TailMatches("GRAPH_TABLE", "("))
4883 else if (TailMatches("GRAPH_TABLE", "(", MatchAny))
4884 COMPLETE_WITH("MATCH");
4885
4886/* GROUP BY */
4887 else if (TailMatches("FROM", MatchAny, "GROUP"))
4888 COMPLETE_WITH("BY");
4889
4890/* IMPORT FOREIGN SCHEMA */
4891 else if (Matches("IMPORT"))
4892 COMPLETE_WITH("FOREIGN SCHEMA");
4893 else if (Matches("IMPORT", "FOREIGN"))
4894 COMPLETE_WITH("SCHEMA");
4895 else if (Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny))
4896 COMPLETE_WITH("EXCEPT (", "FROM SERVER", "LIMIT TO (");
4897 else if (TailMatches("LIMIT", "TO", "(*)") ||
4898 TailMatches("EXCEPT", "(*)"))
4899 COMPLETE_WITH("FROM SERVER");
4900 else if (TailMatches("FROM", "SERVER", MatchAny))
4901 COMPLETE_WITH("INTO");
4902 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO"))
4904 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO", MatchAny))
4905 COMPLETE_WITH("OPTIONS (");
4906
4907/* INSERT --- can be inside EXPLAIN, RULE, etc */
4908 /* Complete NOT MATCHED THEN INSERT */
4909 else if (TailMatches("NOT", "MATCHED", "THEN", "INSERT"))
4910 COMPLETE_WITH("VALUES", "(");
4911 /* Complete INSERT with "INTO" */
4912 else if (TailMatches("INSERT"))
4913 COMPLETE_WITH("INTO");
4914 /* Complete INSERT INTO with table names */
4915 else if (TailMatches("INSERT", "INTO"))
4917 /* Complete "INSERT INTO <table> (" with attribute names */
4918 else if (TailMatches("INSERT", "INTO", MatchAny, "("))
4920
4921 /*
4922 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
4923 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
4924 */
4925 else if (TailMatches("INSERT", "INTO", MatchAny))
4926 COMPLETE_WITH("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
4927
4928 /*
4929 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
4930 * "TABLE" or "OVERRIDING"
4931 */
4932 else if (TailMatches("INSERT", "INTO", MatchAny, MatchAny) &&
4933 ends_with(prev_wd, ')'))
4934 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "OVERRIDING");
4935
4936 /* Complete OVERRIDING */
4937 else if (TailMatches("OVERRIDING"))
4938 COMPLETE_WITH("SYSTEM VALUE", "USER VALUE");
4939
4940 /* Complete after OVERRIDING clause */
4941 else if (TailMatches("OVERRIDING", MatchAny, "VALUE"))
4942 COMPLETE_WITH("SELECT", "TABLE", "VALUES");
4943
4944 /* Insert an open parenthesis after "VALUES" */
4945 else if (TailMatches("VALUES") && !TailMatches("DEFAULT", "VALUES"))
4946 COMPLETE_WITH("(");
4947
4948/* LOCK */
4949 /* Complete LOCK [TABLE] [ONLY] with a list of tables */
4950 else if (Matches("LOCK"))
4952 "TABLE", "ONLY");
4953 else if (Matches("LOCK", "TABLE"))
4955 "ONLY");
4956 else if (Matches("LOCK", "TABLE", "ONLY") || Matches("LOCK", "ONLY"))
4958 /* For the following, handle the case of a single table only for now */
4959
4960 /* Complete LOCK [TABLE] [ONLY] <table> with IN or NOWAIT */
4961 else if (Matches("LOCK", MatchAnyExcept("TABLE|ONLY")) ||
4962 Matches("LOCK", "TABLE", MatchAnyExcept("ONLY")) ||
4963 Matches("LOCK", "ONLY", MatchAny) ||
4964 Matches("LOCK", "TABLE", "ONLY", MatchAny))
4965 COMPLETE_WITH("IN", "NOWAIT");
4966
4967 /* Complete LOCK [TABLE] [ONLY] <table> IN with a lock mode */
4968 else if (Matches("LOCK", MatchAnyN, "IN"))
4969 COMPLETE_WITH("ACCESS SHARE MODE",
4970 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
4971 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
4972 "SHARE ROW EXCLUSIVE MODE",
4973 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
4974
4975 /*
4976 * Complete LOCK [TABLE][ONLY] <table> IN ACCESS|ROW with rest of lock
4977 * mode
4978 */
4979 else if (Matches("LOCK", MatchAnyN, "IN", "ACCESS|ROW"))
4980 COMPLETE_WITH("EXCLUSIVE MODE", "SHARE MODE");
4981
4982 /* Complete LOCK [TABLE] [ONLY] <table> IN SHARE with rest of lock mode */
4983 else if (Matches("LOCK", MatchAnyN, "IN", "SHARE"))
4984 COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE",
4985 "UPDATE EXCLUSIVE MODE");
4986
4987 /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with "NOWAIT" */
4988 else if (Matches("LOCK", MatchAnyN, "MODE"))
4989 COMPLETE_WITH("NOWAIT");
4990
4991/* MERGE --- can be inside EXPLAIN */
4992 else if (TailMatches("MERGE"))
4993 COMPLETE_WITH("INTO");
4994 else if (TailMatches("MERGE", "INTO"))
4996
4997 /* Complete MERGE INTO <table> [[AS] <alias>] with USING */
4998 else if (TailMatches("MERGE", "INTO", MatchAny))
4999 COMPLETE_WITH("USING", "AS");
5000 else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
5001 TailMatches("MERGE", "INTO", MatchAny, MatchAnyExcept("USING|AS")))
5002 COMPLETE_WITH("USING");
5003
5004 /*
5005 * Complete MERGE INTO ... USING with a list of relations supporting
5006 * SELECT
5007 */
5008 else if (TailMatches("MERGE", "INTO", MatchAny, "USING") ||
5009 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING") ||
5010 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING"))
5012
5013 /*
5014 * Complete MERGE INTO <table> [[AS] <alias>] USING <relations> [[AS]
5015 * alias] with ON
5016 */
5017 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny) ||
5018 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny) ||
5019 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny))
5020 COMPLETE_WITH("AS", "ON");
5021 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5022 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5023 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5024 TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
5025 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
5026 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")))
5027 COMPLETE_WITH("ON");
5028
5029 /* Complete MERGE INTO ... ON with target table attributes */
5030 else if (TailMatches("INTO", MatchAny, "USING", MatchAny, "ON"))
5032 else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny, "ON"))
5034 else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAny, "ON"))
5036
5037 /*
5038 * Complete ... USING <relation> [[AS] alias] ON join condition
5039 * (consisting of one or three words typically used) with WHEN [NOT]
5040 * MATCHED
5041 */
5042 else if (TailMatches("USING", MatchAny, "ON", MatchAny) ||
5043 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny) ||
5044 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny) ||
5045 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
5046 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
5047 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")))
5048 COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
5049 else if (TailMatches("USING", MatchAny, "ON", MatchAny, "WHEN") ||
5050 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, "WHEN") ||
5051 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, "WHEN") ||
5052 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
5053 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
5054 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN"))
5055 COMPLETE_WITH("MATCHED", "NOT MATCHED");
5056
5057 /*
5058 * Complete ... WHEN MATCHED and WHEN NOT MATCHED BY SOURCE|TARGET with
5059 * THEN/AND
5060 */
5061 else if (TailMatches("WHEN", "MATCHED") ||
5062 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE|TARGET"))
5063 COMPLETE_WITH("THEN", "AND");
5064
5065 /* Complete ... WHEN NOT MATCHED with BY/THEN/AND */
5066 else if (TailMatches("WHEN", "NOT", "MATCHED"))
5067 COMPLETE_WITH("BY", "THEN", "AND");
5068
5069 /* Complete ... WHEN NOT MATCHED BY with SOURCE/TARGET */
5070 else if (TailMatches("WHEN", "NOT", "MATCHED", "BY"))
5071 COMPLETE_WITH("SOURCE", "TARGET");
5072
5073 /*
5074 * Complete ... WHEN MATCHED THEN and WHEN NOT MATCHED BY SOURCE THEN with
5075 * UPDATE SET/DELETE/DO NOTHING
5076 */
5077 else if (TailMatches("WHEN", "MATCHED", "THEN") ||
5078 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE", "THEN"))
5079 COMPLETE_WITH("UPDATE SET", "DELETE", "DO NOTHING");
5080
5081 /*
5082 * Complete ... WHEN NOT MATCHED [BY TARGET] THEN with INSERT/DO NOTHING
5083 */
5084 else if (TailMatches("WHEN", "NOT", "MATCHED", "THEN") ||
5085 TailMatches("WHEN", "NOT", "MATCHED", "BY", "TARGET", "THEN"))
5086 COMPLETE_WITH("INSERT", "DO NOTHING");
5087
5088/* NOTIFY --- can be inside EXPLAIN, RULE, etc */
5089 else if (TailMatches("NOTIFY"))
5091
5092/* OPTIONS */
5093 else if (TailMatches("OPTIONS"))
5094 COMPLETE_WITH("(");
5095
5096/* OWNER TO - complete with available roles */
5097 else if (TailMatches("OWNER", "TO"))
5100
5101/* ORDER BY */
5102 else if (TailMatches("FROM", MatchAny, "ORDER"))
5103 COMPLETE_WITH("BY");
5104 else if (TailMatches("FROM", MatchAny, "ORDER", "BY"))
5106
5107/* PREPARE xx AS */
5108 else if (Matches("PREPARE", MatchAny, "AS"))
5109 COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM",
5110 "MERGE INTO", "VALUES", "WITH", "TABLE");
5111
5112/*
5113 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
5114 * managers, not for manual use in interactive sessions.
5115 */
5116
5117/* REASSIGN OWNED BY xxx TO yyy */
5118 else if (Matches("REASSIGN"))
5119 COMPLETE_WITH("OWNED BY");
5120 else if (Matches("REASSIGN", "OWNED"))
5121 COMPLETE_WITH("BY");
5122 else if (Matches("REASSIGN", "OWNED", "BY"))
5124 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny))
5125 COMPLETE_WITH("TO");
5126 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
5128
5129/* REFRESH MATERIALIZED VIEW */
5130 else if (Matches("REFRESH"))
5131 COMPLETE_WITH("MATERIALIZED VIEW");
5132 else if (Matches("REFRESH", "MATERIALIZED"))
5133 COMPLETE_WITH("VIEW");
5134 else if (Matches("REFRESH", "MATERIALIZED", "VIEW"))
5136 "CONCURRENTLY");
5137 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
5139 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
5140 COMPLETE_WITH("WITH");
5141 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
5142 COMPLETE_WITH("WITH");
5143 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
5144 COMPLETE_WITH("NO DATA", "DATA");
5145 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
5146 COMPLETE_WITH("NO DATA", "DATA");
5147 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
5148 COMPLETE_WITH("DATA");
5149 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
5150 COMPLETE_WITH("DATA");
5151
5152/* REINDEX */
5153 else if (Matches("REINDEX") ||
5154 Matches("REINDEX", "(*)"))
5155 COMPLETE_WITH("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
5156 else if (Matches("REINDEX", "TABLE") ||
5157 Matches("REINDEX", "(*)", "TABLE"))
5159 "CONCURRENTLY");
5160 else if (Matches("REINDEX", "INDEX") ||
5161 Matches("REINDEX", "(*)", "INDEX"))
5163 "CONCURRENTLY");
5164 else if (Matches("REINDEX", "SCHEMA") ||
5165 Matches("REINDEX", "(*)", "SCHEMA"))
5167 "CONCURRENTLY");
5168 else if (Matches("REINDEX", "SYSTEM|DATABASE") ||
5169 Matches("REINDEX", "(*)", "SYSTEM|DATABASE"))
5171 "CONCURRENTLY");
5172 else if (Matches("REINDEX", "TABLE", "CONCURRENTLY") ||
5173 Matches("REINDEX", "(*)", "TABLE", "CONCURRENTLY"))
5175 else if (Matches("REINDEX", "INDEX", "CONCURRENTLY") ||
5176 Matches("REINDEX", "(*)", "INDEX", "CONCURRENTLY"))
5178 else if (Matches("REINDEX", "SCHEMA", "CONCURRENTLY") ||
5179 Matches("REINDEX", "(*)", "SCHEMA", "CONCURRENTLY"))
5181 else if (Matches("REINDEX", "SYSTEM|DATABASE", "CONCURRENTLY") ||
5182 Matches("REINDEX", "(*)", "SYSTEM|DATABASE", "CONCURRENTLY"))
5184 else if (HeadMatches("REINDEX", "(*") &&
5185 !HeadMatches("REINDEX", "(*)"))
5186 {
5187 /*
5188 * This fires if we're in an unfinished parenthesized option list.
5189 * get_previous_words treats a completed parenthesized option list as
5190 * one word, so the above test is correct.
5191 */
5192 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5193 COMPLETE_WITH("CONCURRENTLY", "TABLESPACE", "VERBOSE");
5194 else if (TailMatches("TABLESPACE"))
5196 }
5197
5198/* REPACK */
5199 else if (Matches("REPACK"))
5201 "(", "USING INDEX");
5202 else if (Matches("REPACK", "(*)"))
5204 "USING INDEX");
5205 else if (Matches("REPACK", MatchAnyExcept("(")))
5206 COMPLETE_WITH("USING INDEX");
5207 else if (Matches("REPACK", "(*)", MatchAnyExcept("(")))
5208 COMPLETE_WITH("USING INDEX");
5209 else if (Matches("REPACK", MatchAny, "USING", "INDEX") ||
5210 Matches("REPACK", "(*)", MatchAny, "USING", "INDEX"))
5211 {
5214 }
5215
5216 /*
5217 * Complete ... [ (*) ] <sth> USING INDEX, with a list of indexes for
5218 * <sth>.
5219 */
5220 else if (TailMatches(MatchAny, "USING", "INDEX"))
5221 {
5224 }
5225 else if (HeadMatches("REPACK", "(*") &&
5226 !HeadMatches("REPACK", "(*)"))
5227 {
5228 /*
5229 * This fires if we're in an unfinished parenthesized option list.
5230 * get_previous_words treats a completed parenthesized option list as
5231 * one word, so the above test is correct.
5232 */
5233 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5234 COMPLETE_WITH("ANALYZE", "VERBOSE");
5235 else if (TailMatches("ANALYZE", "VERBOSE"))
5236 COMPLETE_WITH("ON", "OFF");
5237 }
5238
5239/* SECURITY LABEL */
5240 else if (Matches("SECURITY"))
5241 COMPLETE_WITH("LABEL");
5242 else if (Matches("SECURITY", "LABEL"))
5243 COMPLETE_WITH("ON", "FOR");
5244 else if (Matches("SECURITY", "LABEL", "FOR", MatchAny))
5245 COMPLETE_WITH("ON");
5246 else if (Matches("SECURITY", "LABEL", "ON") ||
5247 Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
5248 COMPLETE_WITH("TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
5249 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION",
5250 "LARGE OBJECT", "MATERIALIZED VIEW", "LANGUAGE",
5251 "PROPERTY GRAPH", "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
5252 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW");
5253 else if (Matches("SECURITY", "LABEL", "ON", "PROPERTY", "GRAPH"))
5255 else if (Matches("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
5256 COMPLETE_WITH("IS");
5257
5258/* SELECT */
5259 /* naah . . . */
5260
5261/* SET, RESET, SHOW */
5262 /* Complete with a variable name */
5263 else if (TailMatches("SET|RESET") &&
5264 !TailMatches("UPDATE", MatchAny, "SET") &&
5265 !TailMatches("ALTER", "DATABASE|USER|ROLE", MatchAny, "RESET"))
5267 "CONSTRAINTS",
5268 "TRANSACTION",
5269 "SESSION",
5270 "ROLE",
5271 "TABLESPACE",
5272 "ALL");
5273 else if (Matches("SHOW"))
5275 "SESSION AUTHORIZATION",
5276 "ALL");
5277 else if (Matches("SHOW", "SESSION"))
5278 COMPLETE_WITH("AUTHORIZATION");
5279 /* Complete "SET TRANSACTION" */
5280 else if (Matches("SET", "TRANSACTION"))
5281 COMPLETE_WITH("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
5282 else if (Matches("BEGIN|START", "TRANSACTION") ||
5283 Matches("BEGIN", "WORK") ||
5284 Matches("BEGIN") ||
5285 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
5286 COMPLETE_WITH("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
5287 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
5288 Matches("BEGIN", "NOT") ||
5289 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
5290 COMPLETE_WITH("DEFERRABLE");
5291 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
5292 Matches("BEGIN", "ISOLATION") ||
5293 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
5294 COMPLETE_WITH("LEVEL");
5295 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
5296 Matches("BEGIN", "ISOLATION", "LEVEL") ||
5297 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
5298 COMPLETE_WITH("READ", "REPEATABLE READ", "SERIALIZABLE");
5299 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
5300 Matches("BEGIN", "ISOLATION", "LEVEL", "READ") ||
5301 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
5302 COMPLETE_WITH("UNCOMMITTED", "COMMITTED");
5303 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
5304 Matches("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
5305 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
5306 COMPLETE_WITH("READ");
5307 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
5308 Matches("BEGIN", "READ") ||
5309 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
5310 COMPLETE_WITH("ONLY", "WRITE");
5311 /* SET CONSTRAINTS */
5312 else if (Matches("SET", "CONSTRAINTS"))
5314 "ALL");
5315 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
5316 else if (Matches("SET", "CONSTRAINTS", MatchAny))
5317 COMPLETE_WITH("DEFERRED", "IMMEDIATE");
5318 /* Complete SET ROLE */
5319 else if (Matches("SET", "ROLE"))
5321 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
5322 else if (Matches("SET", "SESSION"))
5323 COMPLETE_WITH("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
5324 /* Complete SET SESSION AUTHORIZATION with username */
5325 else if (Matches("SET", "SESSION", "AUTHORIZATION"))
5327 "DEFAULT");
5328 /* Complete RESET SESSION with AUTHORIZATION */
5329 else if (Matches("RESET", "SESSION"))
5330 COMPLETE_WITH("AUTHORIZATION");
5331 /* Complete SET <var> with "TO" */
5332 else if (Matches("SET", MatchAny))
5333 COMPLETE_WITH("TO");
5334
5335 /*
5336 * Complete ALTER DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER ... SET
5337 * <name>
5338 */
5339 else if (Matches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER", MatchAnyN, "SET", MatchAnyExcept("SCHEMA")))
5340 COMPLETE_WITH("FROM CURRENT", "TO");
5341
5342 /*
5343 * Suggest possible variable values in SET variable TO|=, along with the
5344 * preceding ALTER syntaxes.
5345 */
5346 else if (TailMatches("SET", MatchAny, "TO|=") &&
5347 !TailMatches("UPDATE", MatchAny, "SET", MatchAny, "TO|="))
5348 {
5349 /* special cased code for individual GUCs */
5350 if (TailMatches("DateStyle", "TO|="))
5351 COMPLETE_WITH("ISO", "SQL", "Postgres", "German",
5352 "YMD", "DMY", "MDY",
5353 "US", "European", "NonEuropean",
5354 "DEFAULT");
5355 else if (TailMatches("search_path", "TO|="))
5356 {
5357 /* Here, we want to allow pg_catalog, so use narrower exclusion */
5359 " AND nspname NOT LIKE E'pg\\\\_toast%%'"
5360 " AND nspname NOT LIKE E'pg\\\\_temp%%'",
5361 "DEFAULT");
5362 }
5363 else if (TailMatches("TimeZone", "TO|="))
5365 else
5366 {
5367 /* generic, type based, GUC support */
5368 char *guctype = get_guctype(prev2_wd);
5369
5370 /*
5371 * Note: if we don't recognize the GUC name, it's important to not
5372 * offer any completions, as most likely we've misinterpreted the
5373 * context and this isn't a GUC-setting command at all.
5374 */
5375 if (guctype)
5376 {
5377 if (strcmp(guctype, "enum") == 0)
5378 {
5381 "DEFAULT");
5382 }
5383 else if (strcmp(guctype, "bool") == 0)
5384 COMPLETE_WITH("on", "off", "true", "false", "yes", "no",
5385 "1", "0", "DEFAULT");
5386 else
5387 COMPLETE_WITH("DEFAULT");
5388
5389 free(guctype);
5390 }
5391 }
5392 }
5393
5394/* START TRANSACTION */
5395 else if (Matches("START"))
5396 COMPLETE_WITH("TRANSACTION");
5397
5398/* TABLE, but not TABLE embedded in other commands */
5399 else if (Matches("TABLE"))
5401
5402/* TABLESAMPLE */
5403 else if (TailMatches("TABLESAMPLE"))
5405 else if (TailMatches("TABLESAMPLE", MatchAny))
5406 COMPLETE_WITH("(");
5407
5408/* TRUNCATE */
5409 else if (Matches("TRUNCATE"))
5411 "TABLE", "ONLY");
5412 else if (Matches("TRUNCATE", "TABLE"))
5414 "ONLY");
5415 else if (Matches("TRUNCATE", MatchAnyN, "ONLY"))
5417 else if (Matches("TRUNCATE", MatchAny) ||
5418 Matches("TRUNCATE", "TABLE|ONLY", MatchAny) ||
5419 Matches("TRUNCATE", "TABLE", "ONLY", MatchAny))
5420 COMPLETE_WITH("RESTART IDENTITY", "CONTINUE IDENTITY", "CASCADE", "RESTRICT");
5421 else if (Matches("TRUNCATE", MatchAnyN, "IDENTITY"))
5422 COMPLETE_WITH("CASCADE", "RESTRICT");
5423
5424/* UNLISTEN */
5425 else if (Matches("UNLISTEN"))
5427
5428/* UPDATE --- can be inside EXPLAIN, RULE, etc */
5429 /* If prev. word is UPDATE suggest a list of tables */
5430 else if (TailMatches("UPDATE"))
5432 /* Complete UPDATE <table> with "SET" */
5433 else if (TailMatches("UPDATE", MatchAny))
5434 COMPLETE_WITH("SET");
5435 /* Complete UPDATE <table> SET with list of attributes */
5436 else if (TailMatches("UPDATE", MatchAny, "SET"))
5438 /* UPDATE <table> SET <attr> = */
5439 else if (TailMatches("UPDATE", MatchAny, "SET", MatchAnyExcept("*=")))
5440 COMPLETE_WITH("=");
5441
5442/* USER MAPPING */
5443 else if (Matches("ALTER|CREATE|DROP", "USER", "MAPPING"))
5444 COMPLETE_WITH("FOR");
5445 else if (Matches("CREATE", "USER", "MAPPING", "FOR"))
5447 "CURRENT_ROLE",
5448 "CURRENT_USER",
5449 "PUBLIC",
5450 "USER");
5451 else if (Matches("ALTER|DROP", "USER", "MAPPING", "FOR"))
5453 else if (Matches("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
5454 COMPLETE_WITH("SERVER");
5455 else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
5456 COMPLETE_WITH("OPTIONS");
5457
5458/*
5459 * VACUUM [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
5460 * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ [ ONLY ] table_and_columns [, ...] ]
5461 */
5462 else if (Matches("VACUUM"))
5464 "(",
5465 "FULL",
5466 "FREEZE",
5467 "VERBOSE",
5468 "ANALYZE",
5469 "ONLY");
5470 else if (HeadMatches("VACUUM", "(*") &&
5471 !HeadMatches("VACUUM", "(*)"))
5472 {
5473 /*
5474 * This fires if we're in an unfinished parenthesized option list.
5475 * get_previous_words treats a completed parenthesized option list as
5476 * one word, so the above test is correct.
5477 */
5478 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5479 COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
5480 "DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
5481 "INDEX_CLEANUP", "PROCESS_MAIN", "PROCESS_TOAST",
5482 "TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
5483 "ONLY_DATABASE_STATS", "BUFFER_USAGE_LIMIT");
5484 else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_MAIN|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
5485 COMPLETE_WITH("ON", "OFF");
5486 else if (TailMatches("INDEX_CLEANUP"))
5487 COMPLETE_WITH("AUTO", "ON", "OFF");
5488 }
5489 else if (Matches("VACUUM", "(*)"))
5491 "ONLY");
5492 else if (Matches("VACUUM", "FULL"))
5494 "FREEZE",
5495 "VERBOSE",
5496 "ANALYZE",
5497 "ONLY");
5498 else if (Matches("VACUUM", MatchAnyN, "FREEZE"))
5500 "VERBOSE",
5501 "ANALYZE",
5502 "ONLY");
5503 else if (Matches("VACUUM", MatchAnyN, "VERBOSE"))
5505 "ANALYZE",
5506 "ONLY");
5507 else if (Matches("VACUUM", MatchAnyN, "ANALYZE"))
5509 "ONLY");
5510 else if (Matches("VACUUM", MatchAnyN, "("))
5511 /* "VACUUM (" should be caught above, so assume we want columns */
5513 else if (HeadMatches("VACUUM"))
5515
5516/*
5517 * WAIT FOR LSN '<lsn>' [ WITH ( option [, ...] ) ]
5518 * where option can be:
5519 * MODE '<mode>'
5520 * TIMEOUT '<timeout>'
5521 * NO_THROW
5522 * and mode can be:
5523 * standby_replay | standby_write | standby_flush | primary_flush
5524 */
5525 else if (Matches("WAIT"))
5526 COMPLETE_WITH("FOR");
5527 else if (Matches("WAIT", "FOR"))
5528 COMPLETE_WITH("LSN");
5529 else if (Matches("WAIT", "FOR", "LSN"))
5530 /* No completion for LSN value - user must provide manually */
5531 ;
5532 else if (Matches("WAIT", "FOR", "LSN", MatchAny))
5533 COMPLETE_WITH("WITH");
5534 else if (Matches("WAIT", "FOR", "LSN", MatchAny, "WITH"))
5535 COMPLETE_WITH("(");
5536
5537 /*
5538 * Handle parenthesized option list. This fires when we're in an
5539 * unfinished parenthesized option list. get_previous_words treats a
5540 * completed parenthesized option list as one word, so the above test is
5541 * correct.
5542 *
5543 * 'mode' takes a string value (one of the listed above), 'timeout' takes
5544 * a string value, and 'no_throw' takes no value. We do not offer
5545 * completions for the *values* of 'timeout' or 'no_throw'.
5546 */
5547 else if (HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*") &&
5548 !HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*)"))
5549 {
5550 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5551 COMPLETE_WITH("mode", "timeout", "no_throw");
5552 else if (TailMatches("mode"))
5553 COMPLETE_WITH("'standby_replay'", "'standby_write'", "'standby_flush'", "'primary_flush'");
5554 }
5555
5556/* WITH [RECURSIVE] */
5557
5558 /*
5559 * Only match when WITH is the first word, as WITH may appear in many
5560 * other contexts.
5561 */
5562 else if (Matches("WITH"))
5563 COMPLETE_WITH("RECURSIVE");
5564
5565/* WHERE */
5566 /* Simple case of the word before the where being the table name */
5567 else if (TailMatches(MatchAny, "WHERE"))
5569
5570/* ... FROM ... */
5571/* TODO: also include SRF ? */
5572 else if (TailMatches("FROM") && !Matches("COPY|\\copy", MatchAny, "FROM"))
5574
5575/* ... JOIN ... */
5576 else if (TailMatches("JOIN"))
5578 else if (TailMatches("JOIN", MatchAny) && !TailMatches("CROSS|NATURAL", "JOIN", MatchAny))
5579 COMPLETE_WITH("ON", "USING (");
5580 else if (TailMatches("JOIN", MatchAny, MatchAny) &&
5581 !TailMatches("CROSS|NATURAL", "JOIN", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5582 COMPLETE_WITH("ON", "USING (");
5583 else if (TailMatches("JOIN", "LATERAL", MatchAny, MatchAny) &&
5584 !TailMatches("CROSS|NATURAL", "JOIN", "LATERAL", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5585 COMPLETE_WITH("ON", "USING (");
5586 else if (TailMatches("JOIN", MatchAny, "USING") ||
5587 TailMatches("JOIN", MatchAny, MatchAny, "USING") ||
5588 TailMatches("JOIN", "LATERAL", MatchAny, MatchAny, "USING"))
5589 COMPLETE_WITH("(");
5590 else if (TailMatches("JOIN", MatchAny, "USING", "("))
5592 else if (TailMatches("JOIN", MatchAny, MatchAny, "USING", "("))
5594
5595/* ... AT [ LOCAL | TIME ZONE ] ... */
5596 else if (TailMatches("AT"))
5597 COMPLETE_WITH("LOCAL", "TIME ZONE");
5598 else if (TailMatches("AT", "TIME", "ZONE"))
5600
5601/* Backslash commands */
5602/* TODO: \dc \dd \dl */
5603 else if (TailMatchesCS("\\?"))
5604 COMPLETE_WITH_CS("commands", "options", "variables");
5605 else if (TailMatchesCS("\\connect|\\c"))
5606 {
5609 }
5610 else if (TailMatchesCS("\\connect|\\c", MatchAny))
5611 {
5614 }
5615 else if (TailMatchesCS("\\da*"))
5617 else if (TailMatchesCS("\\dAc*", MatchAny) ||
5618 TailMatchesCS("\\dAf*", MatchAny))
5620 else if (TailMatchesCS("\\dAo*", MatchAny) ||
5621 TailMatchesCS("\\dAp*", MatchAny))
5623 else if (TailMatchesCS("\\dA*"))
5625 else if (TailMatchesCS("\\db*"))
5627 else if (TailMatchesCS("\\dconfig*"))
5629 else if (TailMatchesCS("\\dD*"))
5631 else if (TailMatchesCS("\\des*"))
5633 else if (TailMatchesCS("\\deu*"))
5635 else if (TailMatchesCS("\\dew*"))
5637 else if (TailMatchesCS("\\df*"))
5639 else if (HeadMatchesCS("\\df*"))
5641
5642 else if (TailMatchesCS("\\dFd*"))
5644 else if (TailMatchesCS("\\dFp*"))
5646 else if (TailMatchesCS("\\dFt*"))
5648 /* must be at end of \dF alternatives: */
5649 else if (TailMatchesCS("\\dF*"))
5651
5652 else if (TailMatchesCS("\\di*"))
5654 else if (TailMatchesCS("\\dL*"))
5656 else if (TailMatchesCS("\\dn*"))
5658 /* no support for completing operators, but we can complete types: */
5659 else if (HeadMatchesCS("\\do*", MatchAny))
5661 else if (TailMatchesCS("\\dp") || TailMatchesCS("\\z"))
5663 else if (TailMatchesCS("\\dPi*"))
5665 else if (TailMatchesCS("\\dPt*"))
5667 else if (TailMatchesCS("\\dP*"))
5669 else if (TailMatchesCS("\\dRp*"))
5671 else if (TailMatchesCS("\\dRs*"))
5673 else if (TailMatchesCS("\\ds*"))
5675 else if (TailMatchesCS("\\dt*"))
5677 else if (TailMatchesCS("\\dT*"))
5679 else if (TailMatchesCS("\\du*") ||
5680 TailMatchesCS("\\dg*") ||
5681 TailMatchesCS("\\drg*"))
5683 else if (TailMatchesCS("\\dv*"))
5685 else if (TailMatchesCS("\\dx*"))
5687 else if (TailMatchesCS("\\dX*"))
5689 else if (TailMatchesCS("\\dm*"))
5691 else if (TailMatchesCS("\\dE*"))
5693 else if (TailMatchesCS("\\dy*"))
5695
5696 /* must be at end of \d alternatives: */
5697 else if (TailMatchesCS("\\d*"))
5699
5700 else if (TailMatchesCS("\\ef"))
5702 else if (TailMatchesCS("\\ev"))
5704
5705 else if (TailMatchesCS("\\encoding"))
5707 else if (TailMatchesCS("\\h|\\help"))
5709 else if (TailMatchesCS("\\h|\\help", MatchAny))
5710 {
5711 if (TailMatches("DROP"))
5713 else if (TailMatches("ALTER"))
5715
5716 /*
5717 * CREATE is recognized by tail match elsewhere, so doesn't need to be
5718 * repeated here
5719 */
5720 }
5721 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny))
5722 {
5723 if (TailMatches("CREATE|DROP", "ACCESS"))
5724 COMPLETE_WITH("METHOD");
5725 else if (TailMatches("ALTER", "DEFAULT"))
5726 COMPLETE_WITH("PRIVILEGES");
5727 else if (TailMatches("CREATE|ALTER|DROP", "EVENT"))
5728 COMPLETE_WITH("TRIGGER");
5729 else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN"))
5730 COMPLETE_WITH("DATA WRAPPER", "TABLE");
5731 else if (TailMatches("ALTER", "LARGE"))
5732 COMPLETE_WITH("OBJECT");
5733 else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED"))
5734 COMPLETE_WITH("VIEW");
5735 else if (TailMatches("CREATE|ALTER|DROP", "PROPERTY"))
5736 COMPLETE_WITH("GRAPH");
5737 else if (TailMatches("CREATE|ALTER|DROP", "TEXT"))
5738 COMPLETE_WITH("SEARCH");
5739 else if (TailMatches("CREATE|ALTER|DROP", "USER"))
5740 COMPLETE_WITH("MAPPING FOR");
5741 }
5742 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny))
5743 {
5744 if (TailMatches("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
5745 COMPLETE_WITH("WRAPPER");
5746 else if (TailMatches("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
5747 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
5748 else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING"))
5749 COMPLETE_WITH("FOR");
5750 }
5751 else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*"))
5753 else if (TailMatchesCS("\\password"))
5755 else if (TailMatchesCS("\\pset"))
5756 COMPLETE_WITH_CS("border", "columns", "csv_fieldsep",
5757 "display_false", "display_true", "expanded",
5758 "fieldsep", "fieldsep_zero", "footer", "format",
5759 "linestyle", "null", "numericlocale",
5760 "pager", "pager_min_lines",
5761 "recordsep", "recordsep_zero",
5762 "tableattr", "title", "tuples_only",
5763 "unicode_border_linestyle",
5764 "unicode_column_linestyle",
5765 "unicode_header_linestyle",
5766 "xheader_width");
5767 else if (TailMatchesCS("\\pset", MatchAny))
5768 {
5769 if (TailMatchesCS("format"))
5770 COMPLETE_WITH_CS("aligned", "asciidoc", "csv", "html", "latex",
5771 "latex-longtable", "troff-ms", "unaligned",
5772 "wrapped");
5773 else if (TailMatchesCS("xheader_width"))
5774 COMPLETE_WITH_CS("full", "column", "page");
5775 else if (TailMatchesCS("linestyle"))
5776 COMPLETE_WITH_CS("ascii", "old-ascii", "unicode");
5777 else if (TailMatchesCS("pager"))
5778 COMPLETE_WITH_CS("on", "off", "always");
5779 else if (TailMatchesCS("unicode_border_linestyle|"
5780 "unicode_column_linestyle|"
5781 "unicode_header_linestyle"))
5782 COMPLETE_WITH_CS("single", "double");
5783 }
5784 else if (TailMatchesCS("\\unset"))
5785 matches = complete_from_variables(text, "", "", true);
5786 else if (TailMatchesCS("\\set"))
5787 matches = complete_from_variables(text, "", "", false);
5788 else if (TailMatchesCS("\\set", MatchAny))
5789 {
5790 if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|SHOW_ALL_RESULTS|"
5791 "SINGLELINE|SINGLESTEP"))
5792 COMPLETE_WITH_CS("on", "off");
5793 else if (TailMatchesCS("COMP_KEYWORD_CASE"))
5794 COMPLETE_WITH_CS("lower", "upper",
5795 "preserve-lower", "preserve-upper");
5796 else if (TailMatchesCS("ECHO"))
5797 COMPLETE_WITH_CS("errors", "queries", "all", "none");
5798 else if (TailMatchesCS("ECHO_HIDDEN"))
5799 COMPLETE_WITH_CS("noexec", "off", "on");
5800 else if (TailMatchesCS("HISTCONTROL"))
5801 COMPLETE_WITH_CS("ignorespace", "ignoredups",
5802 "ignoreboth", "none");
5803 else if (TailMatchesCS("ON_ERROR_ROLLBACK"))
5804 COMPLETE_WITH_CS("on", "off", "interactive");
5805 else if (TailMatchesCS("SHOW_CONTEXT"))
5806 COMPLETE_WITH_CS("never", "errors", "always");
5807 else if (TailMatchesCS("VERBOSITY"))
5808 COMPLETE_WITH_CS("default", "verbose", "terse", "sqlstate");
5809 }
5810 else if (TailMatchesCS("\\sf*"))
5812 else if (TailMatchesCS("\\sv*"))
5814 else if (TailMatchesCS("\\cd|\\e|\\edit|\\g|\\gx|\\i|\\include|"
5815 "\\ir|\\include_relative|\\o|\\out|"
5816 "\\s|\\w|\\write|\\lo_import") ||
5817 TailMatchesCS("\\lo_export", MatchAny))
5818 COMPLETE_WITH_FILES("\\", false);
5819
5820 /* gen_tabcomplete.pl ends special processing here */
5821 /* END GEN_TABCOMPLETE */
5822
5823 return matches;
5824}
5825
5826
5827/*
5828 * GENERATOR FUNCTIONS
5829 *
5830 * These functions do all the actual work of completing the input. They get
5831 * passed the text so far and the count how many times they have been called
5832 * so far with the same text.
5833 * If you read the above carefully, you'll see that these don't get called
5834 * directly but through the readline interface.
5835 * The return value is expected to be the full completion of the text, going
5836 * through a list each time, or NULL if there are no more matches. The string
5837 * will be free()'d by readline, so you must run it through strdup() or
5838 * something of that sort.
5839 */
5840
5841/*
5842 * Common routine for create_command_generator and drop_command_generator.
5843 * Entries that have 'excluded' flags are not returned.
5844 */
5845static char *
5846create_or_drop_command_generator(const char *text, int state, uint32 excluded)
5847{
5848 static int list_index,
5849 string_length;
5850 const char *name;
5851
5852 /* If this is the first time for this completion, init some values */
5853 if (state == 0)
5854 {
5855 list_index = 0;
5856 string_length = strlen(text);
5857 }
5858
5859 /* find something that matches */
5860 while ((name = words_after_create[list_index++].name))
5861 {
5862 if ((pg_strncasecmp(name, text, string_length) == 0) &&
5863 !(words_after_create[list_index - 1].flags & excluded))
5865 }
5866 /* if nothing matches, return NULL */
5867 return NULL;
5868}
5869
5870/*
5871 * This one gives you one from a list of things you can put after CREATE
5872 * as defined above.
5873 */
5874static char *
5875create_command_generator(const char *text, int state)
5876{
5878}
5879
5880/*
5881 * This function gives you a list of things you can put after a DROP command.
5882 */
5883static char *
5884drop_command_generator(const char *text, int state)
5885{
5887}
5888
5889/*
5890 * This function gives you a list of things you can put after an ALTER command.
5891 */
5892static char *
5893alter_command_generator(const char *text, int state)
5894{
5896}
5897
5898/*
5899 * These functions generate lists using server queries.
5900 * They are all wrappers for _complete_from_query.
5901 */
5902
5903static char *
5904complete_from_query(const char *text, int state)
5905{
5906 /* query is assumed to work for any server version */
5909}
5910
5911static char *
5913{
5915
5916 /* Find appropriate array element */
5917 while (pset.sversion < vquery->min_server_version)
5918 vquery++;
5919 /* Fail completion if server is too old */
5920 if (vquery->query == NULL)
5921 return NULL;
5922
5925}
5926
5927static char *
5928complete_from_schema_query(const char *text, int state)
5929{
5930 /* query is assumed to work for any server version */
5933}
5934
5935static char *
5937{
5939
5940 /* Find appropriate array element */
5941 while (pset.sversion < squery->min_server_version)
5942 squery++;
5943 /* Fail completion if server is too old */
5944 if (squery->catname == NULL)
5945 return NULL;
5946
5949}
5950
5951
5952/*
5953 * This creates a list of matching things, according to a query described by
5954 * the initial arguments. The caller has already done any work needed to
5955 * select the appropriate query for the server's version.
5956 *
5957 * The query can be one of two kinds:
5958 *
5959 * 1. A simple query, which must contain a restriction clause of the form
5960 * output LIKE '%s'
5961 * where "output" is the same string that the query returns. The %s
5962 * will be replaced by a LIKE pattern to match the already-typed text.
5963 * There can be a second '%s', which will be replaced by a suitably-escaped
5964 * version of the string provided in completion_ref_object. If there is a
5965 * third '%s', it will be replaced by a suitably-escaped version of the string
5966 * provided in completion_ref_schema. Those strings should be set up
5967 * by calling set_completion_reference or set_completion_reference_verbatim.
5968 * Simple queries should return a single column of matches. If "verbatim"
5969 * is true, the matches are returned as-is; otherwise, they are taken to
5970 * be SQL identifiers and quoted if necessary.
5971 *
5972 * 2. A schema query used for completion of both schema and relation names.
5973 * This is represented by a SchemaQuery object; see that typedef for details.
5974 *
5975 * See top of file for examples of both kinds of query.
5976 *
5977 * In addition to the query itself, we accept a null-terminated array of
5978 * literal keywords, which will be returned if they match the input-so-far
5979 * (case insensitively). (These are in addition to keywords specified
5980 * within the schema_query, if any.)
5981 *
5982 * If "verbatim" is true, then we use the given text as-is to match the
5983 * query results; otherwise we parse it as a possibly-qualified identifier,
5984 * and reconstruct suitable quoting afterward.
5985 *
5986 * "text" and "state" are supplied by Readline. "text" is the word we are
5987 * trying to complete. "state" is zero on first call, nonzero later.
5988 *
5989 * readline will call this repeatedly with the same text and varying
5990 * state. On each call, we are supposed to return a malloc'd string
5991 * that is a candidate completion. Return NULL when done.
5992 */
5993static char *
5996 const char *const *keywords,
5997 bool verbatim,
5998 const char *text, int state)
5999{
6000 static int list_index,
6003 num_keywords;
6004 static PGresult *result = NULL;
6005 static bool non_empty_object;
6006 static bool schemaquoted;
6007 static bool objectquoted;
6008
6009 /*
6010 * If this is the first time for this completion, we fetch a list of our
6011 * "things" from the backend.
6012 */
6013 if (state == 0)
6014 {
6016 char *schemaname;
6017 char *objectname;
6018 char *e_object_like;
6019 char *e_schemaname;
6020 char *e_ref_object;
6021 char *e_ref_schema;
6022
6023 /* Reset static state, ensuring no memory leaks */
6024 list_index = 0;
6025 num_schema_only = 0;
6026 num_query_other = 0;
6027 num_keywords = 0;
6028 PQclear(result);
6029 result = NULL;
6030
6031 /* Parse text, splitting into schema and object name if needed */
6032 if (verbatim)
6033 {
6035 schemaname = NULL;
6036 }
6037 else
6038 {
6040 &schemaname, &objectname,
6042 }
6043
6044 /* Remember whether the user has typed anything in the object part */
6045 non_empty_object = (*objectname != '\0');
6046
6047 /*
6048 * Convert objectname to a LIKE prefix pattern (e.g. 'foo%'), and set
6049 * up suitably-escaped copies of all the strings we need.
6050 */
6052
6053 if (schemaname)
6054 e_schemaname = escape_string(schemaname);
6055 else
6057
6060 else
6062
6065 else
6067
6069
6070 if (schema_query)
6071 {
6073
6074 /*
6075 * We issue different queries depending on whether the input is
6076 * already qualified or not. schema_query gives us the pieces to
6077 * assemble.
6078 */
6079 if (schemaname == NULL || schema_query->namespace == NULL)
6080 {
6081 /* Get unqualified names matching the input-so-far */
6083 if (schema_query->use_distinct)
6084 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
6086 "%s, NULL::pg_catalog.text FROM %s",
6087 schema_query->result,
6088 schema_query->catname);
6089 if (schema_query->refnamespace && completion_ref_schema)
6091 ", pg_catalog.pg_namespace nr");
6093 if (schema_query->selcondition)
6094 appendPQExpBuffer(&query_buffer, "%s AND ",
6095 schema_query->selcondition);
6096 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s'",
6097 schema_query->result,
6099 if (schema_query->viscondition)
6100 appendPQExpBuffer(&query_buffer, " AND %s",
6101 schema_query->viscondition);
6102 if (schema_query->refname)
6103 {
6105 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
6106 schema_query->refname, e_ref_object);
6107 if (schema_query->refnamespace && completion_ref_schema)
6109 " AND %s = nr.oid AND nr.nspname = '%s'",
6110 schema_query->refnamespace,
6111 e_ref_schema);
6112 else if (schema_query->refviscondition)
6114 " AND %s",
6115 schema_query->refviscondition);
6116 }
6117
6118 /*
6119 * When fetching relation names, suppress system catalogs
6120 * unless the input-so-far begins with "pg_". This is a
6121 * compromise between not offering system catalogs for
6122 * completion at all, and having them swamp the result when
6123 * the input is just "p".
6124 */
6125 if (strcmp(schema_query->catname,
6126 "pg_catalog.pg_class c") == 0 &&
6127 strncmp(objectname, "pg_", 3) != 0)
6128 {
6130 " AND c.relnamespace <> (SELECT oid FROM"
6131 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
6132 }
6133
6134 /*
6135 * If the target object type can be schema-qualified, add in
6136 * schema names matching the input-so-far.
6137 */
6138 if (schema_query->namespace)
6139 {
6140 appendPQExpBuffer(&query_buffer, "\nUNION ALL\n"
6141 "SELECT NULL::pg_catalog.text, n.nspname "
6142 "FROM pg_catalog.pg_namespace n "
6143 "WHERE n.nspname LIKE '%s'",
6145
6146 /*
6147 * Likewise, suppress system schemas unless the
6148 * input-so-far begins with "pg_".
6149 */
6150 if (strncmp(objectname, "pg_", 3) != 0)
6152 " AND n.nspname NOT LIKE E'pg\\\\_%'");
6153
6154 /*
6155 * Since we're matching these schema names to the object
6156 * name, handle their quoting using the object name's
6157 * quoting state.
6158 */
6160 }
6161 }
6162 else
6163 {
6164 /* Input is qualified, so produce only qualified names */
6166 if (schema_query->use_distinct)
6167 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
6168 appendPQExpBuffer(&query_buffer, "%s, n.nspname "
6169 "FROM %s, pg_catalog.pg_namespace n",
6170 schema_query->result,
6171 schema_query->catname);
6172 if (schema_query->refnamespace && completion_ref_schema)
6174 ", pg_catalog.pg_namespace nr");
6175 appendPQExpBuffer(&query_buffer, " WHERE %s = n.oid AND ",
6176 schema_query->namespace);
6177 if (schema_query->selcondition)
6178 appendPQExpBuffer(&query_buffer, "%s AND ",
6179 schema_query->selcondition);
6180 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s' AND ",
6181 schema_query->result,
6183 appendPQExpBuffer(&query_buffer, "n.nspname = '%s'",
6184 e_schemaname);
6185 if (schema_query->refname)
6186 {
6188 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
6189 schema_query->refname, e_ref_object);
6190 if (schema_query->refnamespace && completion_ref_schema)
6192 " AND %s = nr.oid AND nr.nspname = '%s'",
6193 schema_query->refnamespace,
6194 e_ref_schema);
6195 else if (schema_query->refviscondition)
6197 " AND %s",
6198 schema_query->refviscondition);
6199 }
6200 }
6201 }
6202 else
6203 {
6205 /* simple_query is an sprintf-style format string */
6209 }
6210
6211 /* Limit the number of records in the result */
6212 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
6214
6215 /* Finally, we can issue the query */
6216 result = exec_query(query_buffer.data);
6217
6218 /* Clean up */
6220 free(schemaname);
6226 }
6227
6228 /* Return the next result, if any, but not if the query failed */
6229 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
6230 {
6231 int nskip;
6232
6233 while (list_index < PQntuples(result))
6234 {
6235 const char *item = NULL;
6236 const char *nsp = NULL;
6237
6238 if (!PQgetisnull(result, list_index, 0))
6239 item = PQgetvalue(result, list_index, 0);
6240 if (PQnfields(result) > 1 &&
6241 !PQgetisnull(result, list_index, 1))
6242 nsp = PQgetvalue(result, list_index, 1);
6243 list_index++;
6244
6245 /* In verbatim mode, we return all the items as-is */
6246 if (verbatim)
6247 {
6249 return pg_strdup(item);
6250 }
6251
6252 /*
6253 * In normal mode, a name requiring quoting will be returned only
6254 * if the input was empty or quoted. Otherwise the user might see
6255 * completion inserting a quote she didn't type, which is
6256 * surprising. This restriction also dodges some odd behaviors of
6257 * some versions of readline/libedit.
6258 */
6259 if (non_empty_object)
6260 {
6261 if (item && !objectquoted && identifier_needs_quotes(item))
6262 continue;
6264 continue;
6265 }
6266
6267 /* Count schema-only results for hack below */
6268 if (item == NULL && nsp != NULL)
6270 else
6272
6274 }
6275
6276 /*
6277 * When the query result is exhausted, check for hard-wired keywords.
6278 * These will only be returned if they match the input-so-far,
6279 * ignoring case.
6280 */
6281 nskip = list_index - PQntuples(result);
6282 if (schema_query && schema_query->keywords)
6283 {
6284 const char *const *itemp = schema_query->keywords;
6285
6286 while (*itemp)
6287 {
6288 const char *item = *itemp++;
6289
6290 if (nskip-- > 0)
6291 continue;
6292 list_index++;
6293 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6294 {
6295 num_keywords++;
6296 return pg_strdup_keyword_case(item, text);
6297 }
6298 }
6299 }
6300 if (keywords)
6301 {
6302 const char *const *itemp = keywords;
6303
6304 while (*itemp)
6305 {
6306 const char *item = *itemp++;
6307
6308 if (nskip-- > 0)
6309 continue;
6310 list_index++;
6311 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6312 {
6313 num_keywords++;
6314 return pg_strdup_keyword_case(item, text);
6315 }
6316 }
6317 }
6318 }
6319
6320 /*
6321 * Hack: if we returned only bare schema names, don't let Readline add a
6322 * space afterwards. Otherwise the schema will stop being part of the
6323 * completion subject text, which is not what we want.
6324 */
6325 if (num_schema_only > 0 && num_query_other == 0 && num_keywords == 0)
6327
6328 /* No more matches, so free the result structure and return null */
6329 PQclear(result);
6330 result = NULL;
6331 return NULL;
6332}
6333
6334
6335/*
6336 * Set up completion_ref_object and completion_ref_schema
6337 * by parsing the given word. These variables can then be
6338 * used in a query passed to _complete_from_query.
6339 */
6340static void
6341set_completion_reference(const char *word)
6342{
6343 bool schemaquoted,
6345
6349}
6350
6351/*
6352 * Set up completion_ref_object when it should just be
6353 * the given word verbatim.
6354 */
6355static void
6357{
6360}
6361
6362
6363/*
6364 * This function returns in order one of a fixed, NULL pointer terminated list
6365 * of strings (if matching). This can be used if there are only a fixed number
6366 * SQL words that can appear at certain spot.
6367 */
6368static char *
6369complete_from_list(const char *text, int state)
6370{
6371 static int string_length,
6372 list_index,
6373 matches;
6374 static bool casesensitive;
6375 const char *item;
6376
6377 /* need to have a list */
6379
6380 /* Initialization */
6381 if (state == 0)
6382 {
6383 list_index = 0;
6384 string_length = strlen(text);
6386 matches = 0;
6387 }
6388
6389 while ((item = completion_charpp[list_index++]))
6390 {
6391 /* First pass is case sensitive */
6392 if (casesensitive && strncmp(text, item, string_length) == 0)
6393 {
6394 matches++;
6395 return pg_strdup(item);
6396 }
6397
6398 /* Second pass is case insensitive, don't bother counting matches */
6399 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
6400 {
6402 return pg_strdup(item);
6403 else
6404
6405 /*
6406 * If case insensitive matching was requested initially,
6407 * adjust the case according to setting.
6408 */
6409 return pg_strdup_keyword_case(item, text);
6410 }
6411 }
6412
6413 /*
6414 * No matches found. If we're not case insensitive already, lets switch to
6415 * being case insensitive and try again
6416 */
6417 if (casesensitive && matches == 0)
6418 {
6419 casesensitive = false;
6420 list_index = 0;
6421 state++;
6422 return complete_from_list(text, state);
6423 }
6424
6425 /* If no more matches, return null. */
6426 return NULL;
6427}
6428
6429
6430/*
6431 * This function returns one fixed string the first time even if it doesn't
6432 * match what's there, and nothing the second time. The string
6433 * to be used must be in completion_charp.
6434 *
6435 * If the given string is "", this has the effect of preventing readline
6436 * from doing any completion. (Without this, readline tries to do filename
6437 * completion which is seldom the right thing.)
6438 *
6439 * If the given string is not empty, readline will replace whatever the
6440 * user typed with that string. This behavior might be useful if it's
6441 * completely certain that we know what must appear at a certain spot,
6442 * so that it's okay to overwrite misspellings. In practice, given the
6443 * relatively lame parsing technology used in this file, the level of
6444 * certainty is seldom that high, so that you probably don't want to
6445 * use this. Use complete_from_list with a one-element list instead;
6446 * that won't try to auto-correct "misspellings".
6447 */
6448static char *
6449complete_from_const(const char *text, int state)
6450{
6452 if (state == 0)
6453 {
6456 else
6457
6458 /*
6459 * If case insensitive matching was requested initially, adjust
6460 * the case according to setting.
6461 */
6463 }
6464 else
6465 return NULL;
6466}
6467
6468
6469/*
6470 * This function appends the variable name with prefix and suffix to
6471 * the variable names array.
6472 */
6473static void
6474append_variable_names(char ***varnames, int *nvars,
6475 int *maxvars, const char *varname,
6476 const char *prefix, const char *suffix)
6477{
6478 if (*nvars >= *maxvars)
6479 {
6480 *maxvars *= 2;
6481 *varnames = pg_realloc_array(*varnames, char *, (*maxvars) + 1);
6482 }
6483
6484 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
6485}
6486
6487
6488/*
6489 * This function supports completion with the name of a psql variable.
6490 * The variable names can be prefixed and suffixed with additional text
6491 * to support quoting usages. If need_value is true, only variables
6492 * that are currently set are included; otherwise, special variables
6493 * (those that have hooks) are included even if currently unset.
6494 */
6495static char **
6496complete_from_variables(const char *text, const char *prefix, const char *suffix,
6497 bool need_value)
6498{
6499 char **matches;
6500 char **varnames;
6501 int nvars = 0;
6502 int maxvars = 100;
6503 int i;
6504 struct _variable *ptr;
6505
6506 varnames = pg_malloc_array(char *, maxvars + 1);
6507
6508 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
6509 {
6510 if (need_value && !(ptr->value))
6511 continue;
6512 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
6513 prefix, suffix);
6514 }
6515
6516 varnames[nvars] = NULL;
6517 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
6518
6519 for (i = 0; i < nvars; i++)
6520 free(varnames[i]);
6521 free(varnames);
6522
6523 return matches;
6524}
6525
6526
6527/*
6528 * This function returns in order one of a fixed, NULL pointer terminated list
6529 * of string that matches file names or optionally specified list of keywords.
6530 *
6531 * If completion_charpp is set to a null-terminated array of literal keywords,
6532 * those keywords are added to the completion results alongside filenames if
6533 * they case-insensitively match the current input.
6534 */
6535static char *
6536complete_from_files(const char *text, int state)
6537{
6538 static int list_index;
6539 static bool files_done;
6540 const char *item;
6541
6542 /* Initialization */
6543 if (state == 0)
6544 {
6545 list_index = 0;
6546 files_done = false;
6547 }
6548
6549 if (!files_done)
6550 {
6551 char *result = _complete_from_files(text, state);
6552
6553 /* Return a filename that matches */
6554 if (result)
6555 return result;
6556
6557 /* There are no more matching files */
6558 files_done = true;
6559 }
6560
6561 if (!completion_charpp)
6562 return NULL;
6563
6564 /*
6565 * Check for hard-wired keywords. These will only be returned if they
6566 * match the input-so-far, ignoring case.
6567 */
6568 while ((item = completion_charpp[list_index++]))
6569 {
6570 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6571 {
6572 completion_force_quote = false;
6573 return pg_strdup_keyword_case(item, text);
6574 }
6575 }
6576
6577 return NULL;
6578}
6579
6580/*
6581 * This function wraps rl_filename_completion_function() to strip quotes from
6582 * the input before searching for matches and to quote any matches for which
6583 * the consuming command will require it.
6584 *
6585 * Caller must set completion_charp to a zero- or one-character string
6586 * containing the escape character. This is necessary since \copy has no
6587 * escape character, but every other backslash command recognizes "\" as an
6588 * escape character.
6589 *
6590 * Caller must also set completion_force_quote to indicate whether to force
6591 * quotes around the result. (The SQL COPY command requires that.)
6592 */
6593static char *
6594_complete_from_files(const char *text, int state)
6595{
6596#ifdef USE_FILENAME_QUOTING_FUNCTIONS
6597
6598 /*
6599 * If we're using a version of Readline that supports filename quoting
6600 * hooks, rely on those, and invoke rl_filename_completion_function()
6601 * without messing with its arguments. Readline does stuff internally
6602 * that does not work well at all if we try to handle dequoting here.
6603 * Instead, Readline will call quote_file_name() and dequote_file_name()
6604 * (see below) at appropriate times.
6605 *
6606 * ... or at least, mostly it will. There are some paths involving
6607 * unmatched file names in which Readline never calls quote_file_name(),
6608 * and if left to its own devices it will incorrectly append a quote
6609 * anyway. Set rl_completion_suppress_quote to prevent that. If we do
6610 * get to quote_file_name(), we'll clear this again. (Yes, this seems
6611 * like it's working around Readline bugs.)
6612 */
6613#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
6615#endif
6616
6617 /* If user typed a quote, force quoting (never remove user's quote) */
6618 if (*text == '\'')
6620
6622#else
6623
6624 /*
6625 * Otherwise, we have to do the best we can.
6626 */
6627 static const char *unquoted_text;
6628 char *unquoted_match;
6629 char *ret = NULL;
6630
6631 /* If user typed a quote, force quoting (never remove user's quote) */
6632 if (*text == '\'')
6634
6635 if (state == 0)
6636 {
6637 /* Initialization: stash the unquoted input. */
6639 false, true, pset.encoding);
6640 /* expect a NULL return for the empty string only */
6641 if (!unquoted_text)
6642 {
6643 Assert(*text == '\0');
6645 }
6646 }
6647
6649 if (unquoted_match)
6650 {
6651 struct stat statbuf;
6652 bool is_dir = (stat(unquoted_match, &statbuf) == 0 &&
6653 S_ISDIR(statbuf.st_mode) != 0);
6654
6655 /* Re-quote the result, if needed. */
6656 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
6657 '\'', *completion_charp,
6659 pset.encoding);
6660 if (ret)
6662 else
6663 ret = unquoted_match;
6664
6665 /*
6666 * If it's a directory, replace trailing quote with a slash; this is
6667 * usually more convenient. (If we didn't quote, leave this to
6668 * libedit.)
6669 */
6670 if (*ret == '\'' && is_dir)
6671 {
6672 char *retend = ret + strlen(ret) - 1;
6673
6674 Assert(*retend == '\'');
6675 *retend = '/';
6676 /* Prevent libedit from adding a space, too */
6678 }
6679 }
6680
6681 return ret;
6682#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
6683}
6684
6685
6686/* HELPER FUNCTIONS */
6687
6688
6689/*
6690 * Make a pg_strdup copy of s and convert the case according to
6691 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
6692 */
6693static char *
6694pg_strdup_keyword_case(const char *s, const char *ref)
6695{
6696 char *ret,
6697 *p;
6698 unsigned char first = ref[0];
6699
6700 ret = pg_strdup(s);
6701
6706 {
6707 for (p = ret; *p; p++)
6708 *p = pg_tolower((unsigned char) *p);
6709 }
6710 else
6711 {
6712 for (p = ret; *p; p++)
6713 *p = pg_toupper((unsigned char) *p);
6714 }
6715
6716 return ret;
6717}
6718
6719
6720/*
6721 * escape_string - Escape argument for use as string literal.
6722 *
6723 * The returned value has to be freed.
6724 */
6725static char *
6726escape_string(const char *text)
6727{
6728 size_t text_length;
6729 char *result;
6730
6732
6733 result = pg_malloc(text_length * 2 + 1);
6735
6736 return result;
6737}
6738
6739
6740/*
6741 * make_like_pattern - Convert argument to a LIKE prefix pattern.
6742 *
6743 * We escape _ and % in the given text by backslashing, append a % to
6744 * represent "any subsequent characters", and then pass the string through
6745 * escape_string() so it's ready to insert in a query. The result needs
6746 * to be freed.
6747 */
6748static char *
6749make_like_pattern(const char *word)
6750{
6751 char *result;
6752 char *buffer = pg_malloc(strlen(word) * 2 + 2);
6753 char *bptr = buffer;
6754
6755 while (*word)
6756 {
6757 if (*word == '_' || *word == '%')
6758 *bptr++ = '\\';
6759 if (IS_HIGHBIT_SET(*word))
6760 {
6761 /*
6762 * Transfer multibyte characters without further processing, to
6763 * avoid getting confused in unsafe client encodings.
6764 */
6766
6767 while (chlen-- > 0)
6768 *bptr++ = *word++;
6769 }
6770 else
6771 *bptr++ = *word++;
6772 }
6773 *bptr++ = '%';
6774 *bptr = '\0';
6775
6776 result = escape_string(buffer);
6777 free(buffer);
6778 return result;
6779}
6780
6781
6782/*
6783 * parse_identifier - Parse a possibly-schema-qualified SQL identifier.
6784 *
6785 * This involves splitting off the schema name if present, de-quoting,
6786 * and downcasing any unquoted text. We are a bit laxer than the backend
6787 * in that we allow just portions of a name to be quoted --- that's because
6788 * psql metacommands have traditionally behaved that way.
6789 *
6790 * Outputs are a malloc'd schema name (NULL if none), malloc'd object name,
6791 * and booleans telling whether any part of the schema and object name was
6792 * double-quoted.
6793 */
6794static void
6795parse_identifier(const char *ident,
6796 char **schemaname, char **objectname,
6797 bool *schemaquoted, bool *objectquoted)
6798{
6799 size_t buflen = strlen(ident) + 1;
6801 char *sname;
6802 char *oname;
6803 char *optr;
6804 bool inquotes;
6805
6806 /* Initialize, making a certainly-large-enough output buffer */
6807 sname = NULL;
6808 oname = pg_malloc(buflen);
6809 *schemaquoted = *objectquoted = false;
6810 /* Scan */
6811 optr = oname;
6812 inquotes = false;
6813 while (*ident)
6814 {
6815 unsigned char ch = (unsigned char) *ident++;
6816
6817 if (ch == '"')
6818 {
6819 if (inquotes && *ident == '"')
6820 {
6821 /* two quote marks within a quoted identifier = emit quote */
6822 *optr++ = '"';
6823 ident++;
6824 }
6825 else
6826 {
6827 inquotes = !inquotes;
6828 *objectquoted = true;
6829 }
6830 }
6831 else if (ch == '.' && !inquotes)
6832 {
6833 /* Found a schema name, transfer it to sname / *schemaquoted */
6834 *optr = '\0';
6835 free(sname); /* drop any catalog name */
6836 sname = oname;
6837 oname = pg_malloc(buflen);
6838 optr = oname;
6840 *objectquoted = false;
6841 }
6842 else if (!enc_is_single_byte && IS_HIGHBIT_SET(ch))
6843 {
6844 /*
6845 * Transfer multibyte characters without further processing. They
6846 * wouldn't be affected by our downcasing rule anyway, and this
6847 * avoids possibly doing the wrong thing in unsafe client
6848 * encodings.
6849 */
6851
6852 *optr++ = (char) ch;
6853 while (--chlen > 0)
6854 *optr++ = *ident++;
6855 }
6856 else
6857 {
6858 if (!inquotes)
6859 {
6860 /*
6861 * This downcasing transformation should match the backend's
6862 * downcase_identifier() as best we can. We do not know the
6863 * backend's locale, though, so it's necessarily approximate.
6864 * We assume that psql is operating in the same locale and
6865 * encoding as the backend.
6866 */
6867 if (ch >= 'A' && ch <= 'Z')
6868 ch += 'a' - 'A';
6870 ch = tolower(ch);
6871 }
6872 *optr++ = (char) ch;
6873 }
6874 }
6875
6876 *optr = '\0';
6877 *schemaname = sname;
6878 *objectname = oname;
6879}
6880
6881
6882/*
6883 * requote_identifier - Reconstruct a possibly-schema-qualified SQL identifier.
6884 *
6885 * Build a malloc'd string containing the identifier, with quoting applied
6886 * as necessary. This is more or less the inverse of parse_identifier;
6887 * in particular, if an input component was quoted, we'll quote the output
6888 * even when that isn't strictly required.
6889 *
6890 * Unlike parse_identifier, we handle the case where a schema and no
6891 * object name is provided, producing just "schema.".
6892 */
6893static char *
6894requote_identifier(const char *schemaname, const char *objectname,
6895 bool quote_schema, bool quote_object)
6896{
6897 char *result;
6898 size_t buflen = 1; /* count the trailing \0 */
6899 char *ptr;
6900
6901 /*
6902 * We could use PQescapeIdentifier for some of this, but not all, and it
6903 * adds more notational cruft than it seems worth.
6904 */
6905 if (schemaname)
6906 {
6907 buflen += strlen(schemaname) + 1; /* +1 for the dot */
6908 if (!quote_schema)
6910 if (quote_schema)
6911 {
6912 buflen += 2; /* account for quote marks */
6913 for (const char *p = schemaname; *p; p++)
6914 {
6915 if (*p == '"')
6916 buflen++;
6917 }
6918 }
6919 }
6920 if (objectname)
6921 {
6922 buflen += strlen(objectname);
6923 if (!quote_object)
6925 if (quote_object)
6926 {
6927 buflen += 2; /* account for quote marks */
6928 for (const char *p = objectname; *p; p++)
6929 {
6930 if (*p == '"')
6931 buflen++;
6932 }
6933 }
6934 }
6935 result = pg_malloc(buflen);
6936 ptr = result;
6937 if (schemaname)
6938 {
6939 if (quote_schema)
6940 *ptr++ = '"';
6941 for (const char *p = schemaname; *p; p++)
6942 {
6943 *ptr++ = *p;
6944 if (*p == '"')
6945 *ptr++ = '"';
6946 }
6947 if (quote_schema)
6948 *ptr++ = '"';
6949 *ptr++ = '.';
6950 }
6951 if (objectname)
6952 {
6953 if (quote_object)
6954 *ptr++ = '"';
6955 for (const char *p = objectname; *p; p++)
6956 {
6957 *ptr++ = *p;
6958 if (*p == '"')
6959 *ptr++ = '"';
6960 }
6961 if (quote_object)
6962 *ptr++ = '"';
6963 }
6964 *ptr = '\0';
6965 return result;
6966}
6967
6968
6969/*
6970 * Detect whether an identifier must be double-quoted.
6971 *
6972 * Note we'll quote anything that's not ASCII; the backend's quote_ident()
6973 * does the same. Perhaps this could be relaxed in future.
6974 */
6975static bool
6976identifier_needs_quotes(const char *ident)
6977{
6978 int kwnum;
6979
6980 /* Check syntax. */
6981 if (!((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_'))
6982 return true;
6983 if (strspn(ident, "abcdefghijklmnopqrstuvwxyz0123456789_$") != strlen(ident))
6984 return true;
6985
6986 /*
6987 * Check for keyword. We quote keywords except for unreserved ones.
6988 *
6989 * It is possible that our keyword list doesn't quite agree with the
6990 * server's, but this should be close enough for tab-completion purposes.
6991 *
6992 * Note: ScanKeywordLookup() does case-insensitive comparison, but that's
6993 * fine, since we already know we have all-lower-case.
6994 */
6996
6998 return true;
6999
7000 return false;
7001}
7002
7003
7004/*
7005 * Execute a query, returning NULL if there was any error.
7006 * This should be the preferred way of talking to the database in this file.
7007 */
7008static PGresult *
7009exec_query(const char *query)
7010{
7011 PGresult *result;
7012
7013 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
7014 return NULL;
7015
7016 result = PQexec(pset.db, query);
7017
7018 if (PQresultStatus(result) != PGRES_TUPLES_OK)
7019 {
7020 /*
7021 * Printing an error while the user is typing would be quite annoying,
7022 * so we don't. This does complicate debugging of this code; but you
7023 * can look in the server log instead.
7024 */
7025#ifdef NOT_USED
7026 pg_log_error("tab completion query failed: %s\nQuery was:\n%s",
7027 PQerrorMessage(pset.db), query);
7028#endif
7029 PQclear(result);
7030 result = NULL;
7031 }
7032
7033 return result;
7034}
7035
7036
7037/*
7038 * Parse all the word(s) before point.
7039 *
7040 * Returns a malloc'd array of character pointers that point into the malloc'd
7041 * data array returned to *buffer; caller must free() both of these when done.
7042 * *nwords receives the number of words found, ie, the valid length of the
7043 * return array.
7044 *
7045 * Words are returned right to left, that is, previous_words[0] gets the last
7046 * word before point, previous_words[1] the next-to-last, etc.
7047 */
7048static char **
7049get_previous_words(int point, char **buffer, int *nwords)
7050{
7051 char **previous_words;
7052 char *buf;
7053 char *outptr;
7054 int words_found = 0;
7055 int i;
7056
7057 /*
7058 * If we have anything in tab_completion_query_buf, paste it together with
7059 * rl_line_buffer to construct the full query. Otherwise we can just use
7060 * rl_line_buffer as the input string.
7061 */
7063 {
7065 buf = pg_malloc(point + i + 2);
7067 buf[i++] = '\n';
7069 i += point;
7070 buf[i] = '\0';
7071 /* Readjust point to reference appropriate offset in buf */
7072 point = i;
7073 }
7074 else
7076
7077 /*
7078 * Allocate an array of string pointers and a buffer to hold the strings
7079 * themselves. The worst case is that the line contains only
7080 * non-whitespace WORD_BREAKS characters, making each one a separate word.
7081 * This is usually much more space than we need, but it's cheaper than
7082 * doing a separate malloc() for each word.
7083 */
7085 *buffer = outptr = (char *) pg_malloc(point * 2);
7086
7087 /*
7088 * First we look for a non-word char before the current point. (This is
7089 * probably useless, if readline is on the same page as we are about what
7090 * is a word, but if so it's cheap.)
7091 */
7092 for (i = point - 1; i >= 0; i--)
7093 {
7094 if (strchr(WORD_BREAKS, buf[i]))
7095 break;
7096 }
7097 point = i;
7098
7099 /*
7100 * Now parse words, working backwards, until we hit start of line. The
7101 * backwards scan has some interesting but intentional properties
7102 * concerning parenthesis handling.
7103 */
7104 while (point >= 0)
7105 {
7106 int start,
7107 end;
7108 bool inquotes = false;
7109 int parentheses = 0;
7110
7111 /* now find the first non-space which then constitutes the end */
7112 end = -1;
7113 for (i = point; i >= 0; i--)
7114 {
7115 if (!isspace((unsigned char) buf[i]))
7116 {
7117 end = i;
7118 break;
7119 }
7120 }
7121 /* if no end found, we're done */
7122 if (end < 0)
7123 break;
7124
7125 /*
7126 * Otherwise we now look for the start. The start is either the last
7127 * character before any word-break character going backwards from the
7128 * end, or it's simply character 0. We also handle open quotes and
7129 * parentheses.
7130 */
7131 for (start = end; start > 0; start--)
7132 {
7133 if (buf[start] == '"')
7134 inquotes = !inquotes;
7135 if (!inquotes)
7136 {
7137 if (buf[start] == ')')
7138 parentheses++;
7139 else if (buf[start] == '(')
7140 {
7141 if (--parentheses <= 0)
7142 break;
7143 }
7144 else if (parentheses == 0 &&
7145 strchr(WORD_BREAKS, buf[start - 1]))
7146 break;
7147 }
7148 }
7149
7150 /* Return the word located at start to end inclusive */
7152 i = end - start + 1;
7153 memcpy(outptr, &buf[start], i);
7154 outptr += i;
7155 *outptr++ = '\0';
7156
7157 /* Continue searching */
7158 point = start - 1;
7159 }
7160
7161 /* Release parsing input workspace, if we made one above */
7162 if (buf != rl_line_buffer)
7163 free(buf);
7164
7165 *nwords = words_found;
7166 return previous_words;
7167}
7168
7169/*
7170 * Look up the type for the GUC variable with the passed name.
7171 *
7172 * Returns NULL if the variable is unknown. Otherwise the returned string,
7173 * containing the type, has to be freed.
7174 */
7175static char *
7176get_guctype(const char *varname)
7177{
7179 char *e_varname;
7180 PGresult *result;
7181 char *guctype = NULL;
7182
7183 e_varname = escape_string(varname);
7184
7187 "SELECT vartype FROM pg_catalog.pg_settings "
7188 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
7189 e_varname);
7190
7191 result = exec_query(query_buffer.data);
7193 free(e_varname);
7194
7195 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
7196 guctype = pg_strdup(PQgetvalue(result, 0, 0));
7197
7198 PQclear(result);
7199
7200 return guctype;
7201}
7202
7203#ifdef USE_FILENAME_QUOTING_FUNCTIONS
7204
7205/*
7206 * Quote a filename according to SQL rules, returning a malloc'd string.
7207 * completion_charp must point to escape character or '\0', and
7208 * completion_force_quote must be set correctly, as per comments for
7209 * complete_from_files().
7210 */
7211static char *
7212quote_file_name(char *fname, int match_type, char *quote_pointer)
7213{
7214 char *s;
7215 struct stat statbuf;
7216
7217 /* Quote if needed. */
7218 s = quote_if_needed(fname, " \t\r\n\"`",
7219 '\'', *completion_charp,
7221 pset.encoding);
7222 if (!s)
7223 s = pg_strdup(fname);
7224
7225 /*
7226 * However, some of the time we have to strip the trailing quote from what
7227 * we send back. Never strip the trailing quote if the user already typed
7228 * one; otherwise, suppress the trailing quote if we have multiple/no
7229 * matches (because we don't want to add a quote if the input is seemingly
7230 * unfinished), or if the input was already quoted (because Readline will
7231 * do arguably-buggy things otherwise), or if the file does not exist, or
7232 * if it's a directory.
7233 */
7234 if (*s == '\'' &&
7235 completion_last_char != '\'' &&
7237 (quote_pointer && *quote_pointer == '\'') ||
7238 stat(fname, &statbuf) != 0 ||
7239 S_ISDIR(statbuf.st_mode)))
7240 {
7241 char *send = s + strlen(s) - 1;
7242
7243 Assert(*send == '\'');
7244 *send = '\0';
7245 }
7246
7247 /*
7248 * And now we can let Readline do its thing with possibly adding a quote
7249 * on its own accord. (This covers some additional cases beyond those
7250 * dealt with above.)
7251 */
7252#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
7254#endif
7255
7256 /*
7257 * If user typed a leading quote character other than single quote (i.e.,
7258 * double quote), zap it, so that we replace it with the correct single
7259 * quote.
7260 */
7261 if (quote_pointer && *quote_pointer != '\'')
7262 *quote_pointer = '\0';
7263
7264 return s;
7265}
7266
7267/*
7268 * Dequote a filename, if it's quoted.
7269 * completion_charp must point to escape character or '\0', as per
7270 * comments for complete_from_files().
7271 */
7272static char *
7273dequote_file_name(char *fname, int quote_char)
7274{
7275 char *unquoted_fname;
7276
7277 /*
7278 * If quote_char is set, it's not included in "fname". We have to add it
7279 * or strtokx will not interpret the string correctly (notably, it won't
7280 * recognize escapes).
7281 */
7282 if (quote_char == '\'')
7283 {
7284 char *workspace = (char *) pg_malloc(strlen(fname) + 2);
7285
7286 workspace[0] = quote_char;
7287 strcpy(workspace + 1, fname);
7288 unquoted_fname = strtokx(workspace, "", NULL, "'", *completion_charp,
7289 false, true, pset.encoding);
7290 free(workspace);
7291 }
7292 else
7293 unquoted_fname = strtokx(fname, "", NULL, "'", *completion_charp,
7294 false, true, pset.encoding);
7295
7296 /* expect a NULL return for the empty string only */
7297 if (!unquoted_fname)
7298 {
7299 Assert(*fname == '\0');
7300 unquoted_fname = fname;
7301 }
7302
7303 /* readline expects a malloc'd result that it is to free */
7304 return pg_strdup(unquoted_fname);
7305}
7306
7307#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
7308
7309#endif /* USE_READLINE */
bool recognized_connection_string(const char *connstr)
Definition common.c:2704
#define IS_HIGHBIT_SET(ch)
Definition c.h:1244
#define Assert(condition)
Definition c.h:943
#define CppAsString2(x)
Definition c.h:506
uint32_t uint32
Definition c.h:624
#define lengthof(array)
Definition c.h:873
varlena text
Definition c.h:789
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition keywords.c:29
Datum arg
Definition elog.c:1322
ConnStatusType PQstatus(const PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition fe-exec.c:4194
PGresult * PQexec(PGconn *conn, const char *query)
Definition fe-exec.c:2279
int PQmblenBounded(const char *s, int encoding)
Definition fe-misc.c:1266
void * pg_malloc(size_t size)
Definition fe_memutils.c:47
char * pg_strdup(const char *in)
Definition fe_memutils.c:85
#define pg_realloc_array(pointer, type, count)
Definition fe_memutils.h:63
#define pg_malloc_array(type, count)
Definition fe_memutils.h:56
return str start
#define ident
int i
Definition isn.c:77
static const JsonPathKeyword keywords[]
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define UNRESERVED_KEYWORD
Definition keywords.h:20
int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)
Definition kwlookup.c:38
#define PQgetvalue
#define PQclear
#define PQnfields
#define PQresultStatus
#define PQgetisnull
#define PQntuples
@ CONNECTION_OK
Definition libpq-fe.h:90
@ PGRES_TUPLES_OK
Definition libpq-fe.h:134
#define pg_log_error(...)
Definition logging.h:106
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1792
static char buf[DEFAULT_XLOG_SEG_SIZE]
int pg_strcasecmp(const char *s1, const char *s2)
unsigned char pg_toupper(unsigned char ch)
unsigned char pg_tolower(unsigned char ch)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
char * c
static int fb(int x)
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition regcomp.c:1476
PsqlSettings pset
Definition startup.c:32
@ PSQL_COMP_CASE_PRESERVE_LOWER
Definition settings.h:66
@ PSQL_COMP_CASE_LOWER
Definition settings.h:68
@ PSQL_COMP_CASE_PRESERVE_UPPER
Definition settings.h:65
#define free(a)
char * strtokx(const char *s, const char *whitespace, const char *delim, const char *quote, char escape, bool e_strings, bool del_quotes, int encoding)
Definition stringutils.c:52
char * quote_if_needed(const char *source, const char *entails_quote, char quote, char escape, bool force_quote, int encoding)
VariableSpace vars
Definition settings.h:151
PSQL_COMP_CASE comp_case
Definition settings.h:179
PGconn * db
Definition settings.h:103
const char * progname
Definition settings.h:142
struct _variable * next
Definition variables.h:68
char * name
Definition variables.h:64
char * value
Definition variables.h:65
Definition c.h:776
void initialize_readline(void)
PQExpBuffer tab_completion_query_buf
static bool escape_string(PGconn *conn, PQExpBuffer target, const char *unescaped, size_t unescaped_len, PQExpBuffer escape_err)
static int32 text_length(Datum str)
Definition varlena.c:410
const char * name
int pg_encoding_max_length(int encoding)
Definition wchar.c:2235
#define stat
Definition win32_port.h:74
#define S_ISDIR(m)
Definition win32_port.h:315
#define send(s, buf, len, flags)
Definition win32_port.h:502