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_parallel_workers",
1436 "autovacuum_vacuum_cost_delay",
1437 "autovacuum_vacuum_cost_limit",
1438 "autovacuum_vacuum_insert_scale_factor",
1439 "autovacuum_vacuum_insert_threshold",
1440 "autovacuum_vacuum_max_threshold",
1441 "autovacuum_vacuum_scale_factor",
1442 "autovacuum_vacuum_threshold",
1443 "fillfactor",
1444 "log_autovacuum_min_duration",
1445 "log_autoanalyze_min_duration",
1446 "parallel_workers",
1447 "toast.autovacuum_enabled",
1448 "toast.autovacuum_freeze_max_age",
1449 "toast.autovacuum_freeze_min_age",
1450 "toast.autovacuum_freeze_table_age",
1451 "toast.autovacuum_multixact_freeze_max_age",
1452 "toast.autovacuum_multixact_freeze_min_age",
1453 "toast.autovacuum_multixact_freeze_table_age",
1454 "toast.autovacuum_vacuum_cost_delay",
1455 "toast.autovacuum_vacuum_cost_limit",
1456 "toast.autovacuum_vacuum_insert_scale_factor",
1457 "toast.autovacuum_vacuum_insert_threshold",
1458 "toast.autovacuum_vacuum_max_threshold",
1459 "toast.autovacuum_vacuum_scale_factor",
1460 "toast.autovacuum_vacuum_threshold",
1461 "toast.log_autovacuum_min_duration",
1462 "toast.vacuum_index_cleanup",
1463 "toast.vacuum_max_eager_freeze_failure_rate",
1464 "toast.vacuum_truncate",
1465 "toast_tuple_target",
1466 "user_catalog_table",
1467 "vacuum_index_cleanup",
1468 "vacuum_max_eager_freeze_failure_rate",
1469 "vacuum_truncate",
1470 NULL
1471};
1472
1473/* Optional parameters for CREATE VIEW and ALTER VIEW */
1474static const char *const view_optional_parameters[] = {
1475 "check_option",
1476 "security_barrier",
1477 "security_invoker",
1478 NULL
1479};
1480
1481/* Forward declaration of functions */
1482static char **psql_completion(const char *text, int start, int end);
1483static char **match_previous_words(int pattern_id,
1484 const char *text, int start, int end,
1485 char **previous_words,
1487static char *create_command_generator(const char *text, int state);
1488static char *drop_command_generator(const char *text, int state);
1489static char *alter_command_generator(const char *text, int state);
1490static char *complete_from_query(const char *text, int state);
1491static char *complete_from_versioned_query(const char *text, int state);
1492static char *complete_from_schema_query(const char *text, int state);
1493static char *complete_from_versioned_schema_query(const char *text, int state);
1494static char *_complete_from_query(const char *simple_query,
1496 const char *const *keywords,
1497 bool verbatim,
1498 const char *text, int state);
1499static void set_completion_reference(const char *word);
1500static void set_completion_reference_verbatim(const char *word);
1501static char *complete_from_list(const char *text, int state);
1502static char *complete_from_const(const char *text, int state);
1503static void append_variable_names(char ***varnames, int *nvars,
1504 int *maxvars, const char *varname,
1505 const char *prefix, const char *suffix);
1506static char **complete_from_variables(const char *text,
1507 const char *prefix, const char *suffix, bool need_value);
1508static char *complete_from_files(const char *text, int state);
1509static char *_complete_from_files(const char *text, int state);
1510
1511static char *pg_strdup_keyword_case(const char *s, const char *ref);
1512static char *escape_string(const char *text);
1513static char *make_like_pattern(const char *word);
1514static void parse_identifier(const char *ident,
1515 char **schemaname, char **objectname,
1516 bool *schemaquoted, bool *objectquoted);
1517static char *requote_identifier(const char *schemaname, const char *objectname,
1518 bool quote_schema, bool quote_object);
1519static bool identifier_needs_quotes(const char *ident);
1520static PGresult *exec_query(const char *query);
1521
1522static char **get_previous_words(int point, char **buffer, int *nwords);
1523
1524static char *get_guctype(const char *varname);
1525
1526#ifdef USE_FILENAME_QUOTING_FUNCTIONS
1527static char *quote_file_name(char *fname, int match_type, char *quote_pointer);
1528static char *dequote_file_name(char *fname, int quote_char);
1529#endif
1530
1531
1532/*
1533 * Initialize the readline library for our purposes.
1534 */
1535void
1537{
1538 rl_readline_name = (char *) pset.progname;
1540
1541#ifdef USE_FILENAME_QUOTING_FUNCTIONS
1544#endif
1545
1547
1548 /*
1549 * Ideally we'd include '"' in rl_completer_quote_characters too, which
1550 * should allow us to complete quoted identifiers that include spaces.
1551 * However, the library support for rl_completer_quote_characters is
1552 * presently too inconsistent to want to mess with that. (Note in
1553 * particular that libedit has this variable but completely ignores it.)
1554 */
1556
1557 /*
1558 * Set rl_filename_quote_characters to "all possible characters",
1559 * otherwise Readline will skip filename quoting if it thinks a filename
1560 * doesn't need quoting. Readline actually interprets this as bytes, so
1561 * there are no encoding considerations here.
1562 */
1563#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
1564 {
1565 unsigned char *fqc = (unsigned char *) pg_malloc(256);
1566
1567 for (int i = 0; i < 255; i++)
1568 fqc[i] = (unsigned char) (i + 1);
1569 fqc[255] = '\0';
1570 rl_filename_quote_characters = (const char *) fqc;
1571 }
1572#endif
1573
1575
1576 /*
1577 * There is a variable rl_completion_query_items for this but apparently
1578 * it's not defined everywhere.
1579 */
1580}
1581
1582/*
1583 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1584 * using case-insensitive or case-sensitive comparisons.
1585 *
1586 * If pattern is NULL, it's a wild card that matches any word.
1587 * If pattern begins with '!', the result is negated, ie we check that 'word'
1588 * does *not* match any alternative appearing in the rest of 'pattern'.
1589 * Any alternative can contain '*' which is a wild card, i.e., it can match
1590 * any substring; however, we allow at most one '*' per alternative.
1591 *
1592 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1593 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1594 * just be written directly in patterns.) There is also MatchAnyN, but that
1595 * is supported only in Matches/MatchesCS and is not handled here.
1596 */
1597static bool
1598word_matches(const char *pattern,
1599 const char *word,
1600 bool case_sensitive)
1601{
1602 size_t wordlen;
1603
1604#define cimatch(s1, s2, n) \
1605 (case_sensitive ? strncmp(s1, s2, n) == 0 : pg_strncasecmp(s1, s2, n) == 0)
1606
1607 /* NULL pattern matches anything. */
1608 if (pattern == NULL)
1609 return true;
1610
1611 /* Handle negated patterns from the MatchAnyExcept macro. */
1612 if (*pattern == '!')
1613 return !word_matches(pattern + 1, word, case_sensitive);
1614
1615 /* Else consider each alternative in the pattern. */
1616 wordlen = strlen(word);
1617 for (;;)
1618 {
1619 const char *star = NULL;
1620 const char *c;
1621
1622 /* Find end of current alternative, and locate any wild card. */
1623 c = pattern;
1624 while (*c != '\0' && *c != '|')
1625 {
1626 if (*c == '*')
1627 star = c;
1628 c++;
1629 }
1630 /* Was there a wild card? */
1631 if (star)
1632 {
1633 /* Yes, wildcard match? */
1634 size_t beforelen = star - pattern,
1635 afterlen = c - star - 1;
1636
1637 if (wordlen >= (beforelen + afterlen) &&
1638 cimatch(word, pattern, beforelen) &&
1639 cimatch(word + wordlen - afterlen, star + 1, afterlen))
1640 return true;
1641 }
1642 else
1643 {
1644 /* No, plain match? */
1645 if (wordlen == (c - pattern) &&
1646 cimatch(word, pattern, wordlen))
1647 return true;
1648 }
1649 /* Out of alternatives? */
1650 if (*c == '\0')
1651 break;
1652 /* Nope, try next alternative. */
1653 pattern = c + 1;
1654 }
1655
1656 return false;
1657}
1658
1659/*
1660 * Implementation of TailMatches and TailMatchesCS tests: do the last N words
1661 * in previous_words match the pattern arguments?
1662 *
1663 * The array indexing might look backwards, but remember that
1664 * previous_words[0] contains the *last* word on the line, not the first.
1665 */
1666static bool
1667TailMatchesArray(bool case_sensitive,
1669 int narg, const char *const *args)
1670{
1672 return false;
1673
1674 for (int argno = 0; argno < narg; argno++)
1675 {
1676 const char *arg = args[argno];
1677
1679 case_sensitive))
1680 return false;
1681 }
1682
1683 return true;
1684}
1685
1686/*
1687 * As above, but the pattern is passed as a variadic argument list.
1688 */
1689static bool
1690TailMatchesImpl(bool case_sensitive,
1692 int narg,...)
1693{
1694 const char *argarray[64];
1695 va_list args;
1696
1698
1700 return false;
1701
1702 va_start(args, narg);
1703 for (int argno = 0; argno < narg; argno++)
1704 argarray[argno] = va_arg(args, const char *);
1705 va_end(args);
1706
1707 return TailMatchesArray(case_sensitive,
1709 narg, argarray);
1710}
1711
1712/*
1713 * Implementation of HeadMatches and HeadMatchesCS tests: do the first N
1714 * words in previous_words match the pattern arguments?
1715 */
1716static bool
1717HeadMatchesArray(bool case_sensitive,
1719 int narg, const char *const *args)
1720{
1722 return false;
1723
1724 for (int argno = 0; argno < narg; argno++)
1725 {
1726 const char *arg = args[argno];
1727
1729 case_sensitive))
1730 return false;
1731 }
1732
1733 return true;
1734}
1735
1736/*
1737 * As above, but the pattern is passed as a variadic argument list.
1738 */
1739static bool
1740HeadMatchesImpl(bool case_sensitive,
1742 int narg,...)
1743{
1744 const char *argarray[64];
1745 va_list args;
1746
1748
1750 return false;
1751
1752 va_start(args, narg);
1753 for (int argno = 0; argno < narg; argno++)
1754 argarray[argno] = va_arg(args, const char *);
1755 va_end(args);
1756
1757 return HeadMatchesArray(case_sensitive,
1759 narg, argarray);
1760}
1761
1762/*
1763 * Implementation of Matches and MatchesCS tests: do all of the words
1764 * in previous_words match the pattern arguments?
1765 *
1766 * This supports an additional kind of wildcard: MatchAnyN (represented as "")
1767 * can match any number of words, including zero, in the middle of the list.
1768 */
1769static bool
1770MatchesArray(bool case_sensitive,
1772 int narg, const char *const *args)
1773{
1774 int match_any_pos = -1;
1775
1776 /* Even with MatchAnyN, there must be at least N-1 words */
1777 if (previous_words_count < narg - 1)
1778 return false;
1779
1780 /* Check for MatchAnyN */
1781 for (int argno = 0; argno < narg; argno++)
1782 {
1783 const char *arg = args[argno];
1784
1785 if (arg != NULL && arg[0] == '\0')
1786 {
1788 break;
1789 }
1790 }
1791
1792 if (match_any_pos < 0)
1793 {
1794 /* Standard case without MatchAnyN */
1796 return false;
1797
1798 /* Either Head or Tail match will do for the rest */
1799 if (!HeadMatchesArray(case_sensitive,
1801 narg, args))
1802 return false;
1803 }
1804 else
1805 {
1806 /* Match against head */
1807 if (!HeadMatchesArray(case_sensitive,
1809 match_any_pos, args))
1810 return false;
1811
1812 /* Match against tail */
1813 if (!TailMatchesArray(case_sensitive,
1815 narg - match_any_pos - 1,
1816 args + match_any_pos + 1))
1817 return false;
1818 }
1819
1820 return true;
1821}
1822
1823/*
1824 * As above, but the pattern is passed as a variadic argument list.
1825 */
1826static bool
1827MatchesImpl(bool case_sensitive,
1829 int narg,...)
1830{
1831 const char *argarray[64];
1832 va_list args;
1833
1835
1836 /* Even with MatchAnyN, there must be at least N-1 words */
1837 if (previous_words_count < narg - 1)
1838 return false;
1839
1840 va_start(args, narg);
1841 for (int argno = 0; argno < narg; argno++)
1842 argarray[argno] = va_arg(args, const char *);
1843 va_end(args);
1844
1845 return MatchesArray(case_sensitive,
1847 narg, argarray);
1848}
1849
1850/*
1851 * Check if the final character of 's' is 'c'.
1852 */
1853static bool
1854ends_with(const char *s, char c)
1855{
1856 size_t length = strlen(s);
1857
1858 return (length > 0 && s[length - 1] == c);
1859}
1860
1861/*
1862 * The completion function.
1863 *
1864 * According to readline spec this gets passed the text entered so far and its
1865 * start and end positions in the readline buffer. The return value is some
1866 * partially obscure list format that can be generated by readline's
1867 * rl_completion_matches() function, so we don't have to worry about it.
1868 */
1869static char **
1870psql_completion(const char *text, int start, int end)
1871{
1872 /* This is the variable we'll return. */
1873 char **matches = NULL;
1874
1875 /* Workspace for parsed words. */
1876 char *words_buffer;
1877
1878 /* This array will contain pointers to parsed words. */
1879 char **previous_words;
1880
1881 /* The number of words found on the input line. */
1883
1884 /*
1885 * For compactness, we use these macros to reference previous_words[].
1886 * Caution: do not access a previous_words[] entry without having checked
1887 * previous_words_count to be sure it's valid. In most cases below, that
1888 * check is implicit in a TailMatches() or similar macro, but in some
1889 * places we have to check it explicitly.
1890 */
1891#define prev_wd (previous_words[0])
1892#define prev2_wd (previous_words[1])
1893#define prev3_wd (previous_words[2])
1894#define prev4_wd (previous_words[3])
1895#define prev5_wd (previous_words[4])
1896#define prev6_wd (previous_words[5])
1897#define prev7_wd (previous_words[6])
1898#define prev8_wd (previous_words[7])
1899#define prev9_wd (previous_words[8])
1900
1901 /* Match the last N words before point, case-insensitively. */
1902#define TailMatches(...) \
1903 TailMatchesImpl(false, previous_words_count, previous_words, \
1904 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1905
1906 /* Match the last N words before point, case-sensitively. */
1907#define TailMatchesCS(...) \
1908 TailMatchesImpl(true, previous_words_count, previous_words, \
1909 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1910
1911 /* Match N words representing all of the line, case-insensitively. */
1912#define Matches(...) \
1913 MatchesImpl(false, previous_words_count, previous_words, \
1914 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1915
1916 /* Match N words representing all of the line, case-sensitively. */
1917#define MatchesCS(...) \
1918 MatchesImpl(true, previous_words_count, previous_words, \
1919 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1920
1921 /* Match the first N words on the line, case-insensitively. */
1922#define HeadMatches(...) \
1923 HeadMatchesImpl(false, previous_words_count, previous_words, \
1924 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1925
1926 /* Match the first N words on the line, case-sensitively. */
1927#define HeadMatchesCS(...) \
1928 HeadMatchesImpl(true, previous_words_count, previous_words, \
1929 VA_ARGS_NARGS(__VA_ARGS__), __VA_ARGS__)
1930
1931 /* psql's backslash commands. */
1932 static const char *const backslash_commands[] = {
1933 "\\a",
1934 "\\bind", "\\bind_named",
1935 "\\connect", "\\conninfo", "\\C", "\\cd", "\\close_prepared", "\\copy",
1936 "\\copyright", "\\crosstabview",
1937 "\\d", "\\da", "\\dA", "\\dAc", "\\dAf", "\\dAo", "\\dAp",
1938 "\\db", "\\dc", "\\dconfig", "\\dC", "\\dd", "\\ddp", "\\dD",
1939 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1940 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1941 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\dP", "\\dPi", "\\dPt",
1942 "\\drds", "\\drg", "\\dRs", "\\dRp", "\\ds",
1943 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dX", "\\dy",
1944 "\\echo", "\\edit", "\\ef", "\\elif", "\\else", "\\encoding",
1945 "\\endif", "\\endpipeline", "\\errverbose", "\\ev",
1946 "\\f", "\\flush", "\\flushrequest",
1947 "\\g", "\\gdesc", "\\getenv", "\\getresults", "\\gexec", "\\gset", "\\gx",
1948 "\\help", "\\html",
1949 "\\if", "\\include", "\\include_relative", "\\ir",
1950 "\\list", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1951 "\\out",
1952 "\\parse", "\\password", "\\print", "\\prompt", "\\pset",
1953 "\\qecho", "\\quit",
1954 "\\reset", "\\restrict",
1955 "\\s", "\\sendpipeline", "\\set", "\\setenv", "\\sf",
1956 "\\startpipeline", "\\sv", "\\syncpipeline",
1957 "\\t", "\\T", "\\timing",
1958 "\\unrestrict", "\\unset",
1959 "\\x",
1960 "\\warn", "\\watch", "\\write",
1961 "\\z",
1962 "\\!", "\\?",
1963 NULL
1964 };
1965
1966 /*
1967 * Temporary workaround for a bug in recent (2019) libedit: it incorrectly
1968 * de-escapes the input "text", causing us to fail to recognize backslash
1969 * commands. So get the string to look at from rl_line_buffer instead.
1970 */
1971 char *text_copy = pnstrdup(rl_line_buffer + start, end - start);
1972 text = text_copy;
1973
1974 /* Remember last char of the given input word. */
1975 completion_last_char = (end > start) ? text[end - start - 1] : '\0';
1976
1977 /* We usually want the append character to be a space. */
1979
1980 /* Clear a few things. */
1987
1988 /*
1989 * Scan the input line to extract the words before our current position.
1990 * According to those we'll make some smart decisions on what the user is
1991 * probably intending to type.
1992 */
1994 &words_buffer,
1996
1997 /* If current word is a backslash command, offer completions for that */
1998 if (text[0] == '\\')
2000
2001 /* If current word is a variable interpolation, handle that case */
2002 else if (text[0] == ':' && text[1] != ':')
2003 {
2004 if (text[1] == '\'')
2005 matches = complete_from_variables(text, ":'", "'", true);
2006 else if (text[1] == '"')
2007 matches = complete_from_variables(text, ":\"", "\"", true);
2008 else if (text[1] == '{' && text[2] == '?')
2009 matches = complete_from_variables(text, ":{?", "}", true);
2010 else
2011 matches = complete_from_variables(text, ":", "", true);
2012 }
2013
2014 /* If no previous word, suggest one of the basic sql commands */
2015 else if (previous_words_count == 0)
2017
2018 /* Else try completions based on matching patterns of previous words */
2019 else
2020 {
2021#ifdef SWITCH_CONVERSION_APPLIED
2022 /*
2023 * If we have transformed match_previous_words into a switch, iterate
2024 * through tcpatterns[] to see which pattern ids match.
2025 *
2026 * For now, we have to try the patterns in the order they are stored
2027 * (matching the order of switch cases in match_previous_words),
2028 * because some of the logic in match_previous_words assumes that
2029 * previous matches have been eliminated. This is fairly
2030 * unprincipled, and it is likely that there are undesirable as well
2031 * as desirable interactions hidden in the order of the pattern
2032 * checks. TODO: think about a better way to manage that.
2033 */
2034 for (int tindx = 0; tindx < lengthof(tcpatterns); tindx++)
2035 {
2036 const TCPattern *tcpat = tcpatterns + tindx;
2037 bool match = false;
2038
2039 switch (tcpat->kind)
2040 {
2041 case Match:
2042 match = MatchesArray(false,
2045 tcpat->nwords, tcpat->words);
2046 break;
2047 case MatchCS:
2048 match = MatchesArray(true,
2051 tcpat->nwords, tcpat->words);
2052 break;
2053 case HeadMatch:
2054 match = HeadMatchesArray(false,
2057 tcpat->nwords, tcpat->words);
2058 break;
2059 case HeadMatchCS:
2060 match = HeadMatchesArray(true,
2063 tcpat->nwords, tcpat->words);
2064 break;
2065 case TailMatch:
2066 match = TailMatchesArray(false,
2069 tcpat->nwords, tcpat->words);
2070 break;
2071 case TailMatchCS:
2072 match = TailMatchesArray(true,
2075 tcpat->nwords, tcpat->words);
2076 break;
2077 }
2078 if (match)
2079 {
2083 if (matches != NULL)
2084 break;
2085 }
2086 }
2087#else /* !SWITCH_CONVERSION_APPLIED */
2088 /*
2089 * If gen_tabcomplete.pl hasn't been applied to this code, just let
2090 * match_previous_words scan through all its patterns.
2091 */
2095#endif /* SWITCH_CONVERSION_APPLIED */
2096 }
2097
2098 /*
2099 * Finally, we look through the list of "things", such as TABLE, INDEX and
2100 * check if that was the previous word. If so, execute the query to get a
2101 * list of them.
2102 */
2103 if (matches == NULL && previous_words_count > 0)
2104 {
2105 const pgsql_thing_t *wac;
2106
2107 for (wac = words_after_create; wac->name != NULL; wac++)
2108 {
2109 if (pg_strcasecmp(prev_wd, wac->name) == 0)
2110 {
2111 if (wac->query)
2113 wac->keywords);
2114 else if (wac->vquery)
2116 wac->keywords);
2117 else if (wac->squery)
2119 wac->keywords);
2120 break;
2121 }
2122 }
2123 }
2124
2125 /*
2126 * If we still don't have anything to match we have to fabricate some sort
2127 * of default list. If we were to just return NULL, readline automatically
2128 * attempts filename completion, and that's usually no good.
2129 */
2130 if (matches == NULL)
2131 {
2132 COMPLETE_WITH_CONST(true, "");
2133 /* Also, prevent Readline from appending stuff to the non-match */
2135#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
2137#endif
2138 }
2139
2140 /* free storage */
2143 free(text_copy);
2148
2149 /* Return our Grand List O' Matches */
2150 return matches;
2151}
2152
2153/*
2154 * Subroutine to try matches based on previous_words.
2155 *
2156 * This can operate in one of two modes. As presented, the body of the
2157 * function is a long if-else-if chain that sequentially tries each known
2158 * match rule. That works, but some C compilers have trouble with such a long
2159 * else-if chain, either taking extra time to compile or failing altogether.
2160 * Therefore, we prefer to transform the else-if chain into a switch, and then
2161 * each call of this function considers just one match rule (under control of
2162 * a loop in psql_completion()). Compilers tend to be more ready to deal
2163 * with many-arm switches than many-arm else-if chains.
2164 *
2165 * Each if-condition in this function must begin with a call of one of the
2166 * functions Matches, HeadMatches, TailMatches, MatchesCS, HeadMatchesCS, or
2167 * TailMatchesCS. The preprocessor gen_tabcomplete.pl strips out those
2168 * calls and converts them into entries in tcpatterns[], which are evaluated
2169 * by the calling loop in psql_completion(). Successful matches result in
2170 * calls to this function with the appropriate pattern_id, causing just the
2171 * corresponding switch case to be executed.
2172 *
2173 * If-conditions in this function can be more complex than a single *Matches
2174 * function call in one of two ways (but not both!). They can be OR's
2175 * of *Matches calls, such as
2176 * else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
2177 * Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
2178 * or they can be a *Matches call AND'ed with some other condition, e.g.
2179 * else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) &&
2180 * !ends_with(prev_wd, ','))
2181 * The former case is transformed into multiple tcpatterns[] entries and
2182 * multiple case labels for the same bit of code. The latter case is
2183 * transformed into a case label and a contained if-statement.
2184 *
2185 * This is split out of psql_completion() primarily to separate code that
2186 * gen_tabcomplete.pl should process from code that it should not, although
2187 * doing so also helps to avoid extra indentation of this code.
2188 *
2189 * Returns a matches list, or NULL if no match.
2190 */
2191static char **
2193 const char *text, int start, int end,
2195{
2196 /* This is the variable we'll return. */
2197 char **matches = NULL;
2198
2199 /* Dummy statement, allowing all the match rules to look like "else if" */
2200 if (0)
2201 {
2202 /* skip */
2203 }
2204
2205 /* gen_tabcomplete.pl begins special processing here */
2206 /* BEGIN GEN_TABCOMPLETE */
2207
2208/* CREATE */
2209 /* complete with something you can create */
2210 else if (TailMatches("CREATE"))
2211 {
2212 /* only some object types can be created as part of CREATE SCHEMA */
2213 if (HeadMatches("CREATE", "SCHEMA"))
2214 COMPLETE_WITH("AGGREGATE", "COLLATION", "DOMAIN", "FUNCTION",
2215 "INDEX", "OPERATOR", "PROCEDURE", "SEQUENCE", "TABLE",
2216 "TEXT SEARCH CONFIGURATION", "TEXT SEARCH DICTIONARY",
2217 "TEXT SEARCH PARSER", "TEXT SEARCH TEMPLATE",
2218 "TRIGGER", "TYPE", "VIEW",
2219 /* for INDEX and TABLE/SEQUENCE, respectively */
2220 "UNIQUE", "UNLOGGED");
2221 else
2223 }
2224 /* complete with something you can create or replace */
2225 else if (TailMatches("CREATE", "OR", "REPLACE"))
2226 COMPLETE_WITH("FUNCTION", "PROCEDURE", "LANGUAGE", "RULE", "VIEW",
2227 "AGGREGATE", "TRANSFORM", "TRIGGER");
2228
2229/* DROP, but not DROP embedded in other commands */
2230 /* complete with something you can drop */
2231 else if (Matches("DROP"))
2233
2234/* ALTER */
2235
2236 /* ALTER TABLE */
2237 else if (Matches("ALTER", "TABLE"))
2239 "ALL IN TABLESPACE");
2240
2241 /* ALTER something */
2242 else if (Matches("ALTER"))
2244 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
2245 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny))
2246 COMPLETE_WITH("SET TABLESPACE", "OWNED BY");
2247 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
2248 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
2250 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
2251 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
2252 COMPLETE_WITH("SET TABLESPACE");
2253 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
2254 else if (Matches("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
2255 COMPLETE_WITH("(");
2256 /* ALTER AGGREGATE <name> (...) */
2257 else if (Matches("ALTER", "AGGREGATE", MatchAny, MatchAny))
2258 {
2259 if (ends_with(prev_wd, ')'))
2260 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
2261 else
2263 }
2264 /* ALTER FUNCTION <name> (...) */
2265 else if (Matches("ALTER", "FUNCTION", MatchAny, MatchAny))
2266 {
2267 if (ends_with(prev_wd, ')'))
2269 else
2271 }
2272 /* ALTER PROCEDURE <name> (...) */
2273 else if (Matches("ALTER", "PROCEDURE", MatchAny, MatchAny))
2274 {
2275 if (ends_with(prev_wd, ')'))
2277 else
2279 }
2280 /* ALTER ROUTINE <name> (...) */
2281 else if (Matches("ALTER", "ROUTINE", MatchAny, MatchAny))
2282 {
2283 if (ends_with(prev_wd, ')'))
2285 else
2287 }
2288 /* ALTER FUNCTION|ROUTINE <name> (...) PARALLEL */
2289 else if (Matches("ALTER", "FUNCTION|ROUTINE", MatchAny, MatchAny, "PARALLEL"))
2290 COMPLETE_WITH("RESTRICTED", "SAFE", "UNSAFE");
2291 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) [EXTERNAL] SECURITY */
2292 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SECURITY") ||
2293 Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "EXTERNAL", "SECURITY"))
2294 COMPLETE_WITH("DEFINER", "INVOKER");
2295 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) RESET */
2296 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "RESET"))
2298 "ALL");
2299 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) SET */
2300 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SET"))
2302 "SCHEMA");
2303
2304 /* ALTER PUBLICATION <name> */
2305 else if (Matches("ALTER", "PUBLICATION", MatchAny))
2306 COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME TO", "SET");
2307 /* ALTER PUBLICATION <name> ADD */
2308 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD"))
2309 COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
2310 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
2312 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
2313 ends_with(prev_wd, ','))
2315
2316 /*
2317 * "ALTER PUBLICATION <name> SET TABLE <name> WHERE (" - complete with
2318 * table attributes
2319 *
2320 * "ALTER PUBLICATION <name> ADD TABLE <name> WHERE (" - complete with
2321 * table attributes
2322 */
2323 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "WHERE"))
2324 COMPLETE_WITH("(");
2325 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "("))
2327 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
2328 !TailMatches("WHERE", "(*)"))
2329 COMPLETE_WITH(",", "WHERE (");
2330 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
2331 COMPLETE_WITH(",");
2332 /* ALTER PUBLICATION <name> DROP */
2333 else if (Matches("ALTER", "PUBLICATION", MatchAny, "DROP"))
2334 COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
2335 /* ALTER PUBLICATION <name> SET */
2336 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
2337 COMPLETE_WITH("(", "ALL SEQUENCES", "ALL TABLES", "TABLES IN SCHEMA", "TABLE");
2338 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL"))
2339 COMPLETE_WITH("SEQUENCES", "TABLES");
2340 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES"))
2341 COMPLETE_WITH("EXCEPT ( TABLE");
2342 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT"))
2343 COMPLETE_WITH("( TABLE");
2344 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "("))
2345 COMPLETE_WITH("TABLE");
2346 /* Complete "ALTER PUBLICATION <name> FOR TABLE" with "<table>, ..." */
2347 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "(", "TABLE"))
2349 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd, ','))
2351 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd, ','))
2352 COMPLETE_WITH(")");
2353 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|DROP|SET", "TABLES", "IN", "SCHEMA"))
2355 " AND nspname NOT LIKE E'pg\\\\_%%'",
2356 "CURRENT_SCHEMA");
2357 /* ALTER PUBLICATION <name> SET ( */
2358 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "SET", "("))
2359 COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root");
2360 /* ALTER SUBSCRIPTION <name> */
2361 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny))
2362 COMPLETE_WITH("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
2363 "RENAME TO", "REFRESH PUBLICATION", "REFRESH SEQUENCES",
2364 "SERVER", "SET", "SKIP (", "ADD PUBLICATION", "DROP PUBLICATION");
2365 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SERVER"))
2367 /* ALTER SUBSCRIPTION <name> REFRESH */
2368 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH"))
2369 COMPLETE_WITH("PUBLICATION", "SEQUENCES");
2370 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
2371 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH", "PUBLICATION", "WITH", "("))
2372 COMPLETE_WITH("copy_data");
2373 /* ALTER SUBSCRIPTION <name> SET */
2374 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
2375 COMPLETE_WITH("(", "PUBLICATION");
2376 /* ALTER SUBSCRIPTION <name> SET ( */
2377 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "("))
2378 COMPLETE_WITH("binary", "disable_on_error", "failover",
2379 "max_retention_duration", "origin",
2380 "password_required", "retain_dead_tuples",
2381 "run_as_owner", "slot_name", "streaming",
2382 "synchronous_commit", "two_phase");
2383 /* ALTER SUBSCRIPTION <name> SKIP ( */
2384 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SKIP", "("))
2385 COMPLETE_WITH("lsn");
2386 /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
2387 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "PUBLICATION"))
2388 {
2389 /* complete with nothing here as this refers to remote publications */
2390 }
2391 /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> */
2392 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN,
2393 "ADD|DROP|SET", "PUBLICATION", MatchAny))
2394 COMPLETE_WITH("WITH (");
2395 /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> WITH ( */
2396 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN,
2397 "ADD|DROP|SET", "PUBLICATION", MatchAny, "WITH", "("))
2398 COMPLETE_WITH("copy_data", "refresh");
2399
2400 /* ALTER SCHEMA <name> */
2401 else if (Matches("ALTER", "SCHEMA", MatchAny))
2402 COMPLETE_WITH("OWNER TO", "RENAME TO");
2403
2404 /* ALTER COLLATION <name> */
2405 else if (Matches("ALTER", "COLLATION", MatchAny))
2406 COMPLETE_WITH("OWNER TO", "REFRESH VERSION", "RENAME TO", "SET SCHEMA");
2407
2408 /* ALTER CONVERSION <name> */
2409 else if (Matches("ALTER", "CONVERSION", MatchAny))
2410 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
2411
2412 /* ALTER DATABASE <name> */
2413 else if (Matches("ALTER", "DATABASE", MatchAny))
2414 COMPLETE_WITH("RESET", "SET", "OWNER TO", "REFRESH COLLATION VERSION", "RENAME TO",
2415 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
2416 "CONNECTION LIMIT");
2417
2418 /* ALTER DATABASE <name> RESET */
2419 else if (Matches("ALTER", "DATABASE", MatchAny, "RESET"))
2420 {
2423 }
2424
2425 /* ALTER DATABASE <name> SET TABLESPACE */
2426 else if (Matches("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE"))
2428
2429 /* ALTER EVENT TRIGGER */
2430 else if (Matches("ALTER", "EVENT", "TRIGGER"))
2432
2433 /* ALTER EVENT TRIGGER <name> */
2434 else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny))
2435 COMPLETE_WITH("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
2436
2437 /* ALTER EVENT TRIGGER <name> ENABLE */
2438 else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
2439 COMPLETE_WITH("REPLICA", "ALWAYS");
2440
2441 /* ALTER EXTENSION <name> */
2442 else if (Matches("ALTER", "EXTENSION", MatchAny))
2443 COMPLETE_WITH("ADD", "DROP", "UPDATE", "SET SCHEMA");
2444
2445 /* ALTER EXTENSION <name> ADD|DROP */
2446 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP"))
2447 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
2448 "CONVERSION", "DOMAIN", "EVENT TRIGGER", "FOREIGN",
2449 "FUNCTION", "MATERIALIZED VIEW", "OPERATOR",
2450 "LANGUAGE", "PROCEDURE", "ROUTINE", "SCHEMA",
2451 "SEQUENCE", "SERVER", "TABLE", "TEXT SEARCH",
2452 "TRANSFORM FOR", "TYPE", "VIEW");
2453
2454 /* ALTER EXTENSION <name> ADD|DROP FOREIGN */
2455 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "FOREIGN"))
2456 COMPLETE_WITH("DATA WRAPPER", "TABLE");
2457
2458 /* ALTER EXTENSION <name> ADD|DROP OPERATOR */
2459 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "OPERATOR"))
2460 COMPLETE_WITH("CLASS", "FAMILY");
2461
2462 /* ALTER EXTENSION <name> ADD|DROP TEXT SEARCH */
2463 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "TEXT", "SEARCH"))
2464 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2465
2466 /* ALTER EXTENSION <name> UPDATE */
2467 else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE"))
2468 COMPLETE_WITH("TO");
2469
2470 /* ALTER EXTENSION <name> UPDATE TO */
2471 else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
2472 {
2475 }
2476
2477 /* ALTER FOREIGN */
2478 else if (Matches("ALTER", "FOREIGN"))
2479 COMPLETE_WITH("DATA WRAPPER", "TABLE");
2480
2481 /* ALTER FOREIGN DATA WRAPPER <name> */
2482 else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2483 COMPLETE_WITH("CONNECTION", "HANDLER", "NO",
2484 "OPTIONS", "OWNER TO", "RENAME TO", "VALIDATOR");
2485 else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny, "NO"))
2486 COMPLETE_WITH("CONNECTION", "HANDLER", "VALIDATOR");
2487
2488 /* ALTER FOREIGN TABLE <name> */
2489 else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny))
2490 COMPLETE_WITH("ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE",
2491 "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO",
2492 "RENAME", "SET", "VALIDATE CONSTRAINT");
2493
2494 /* ALTER INDEX */
2495 else if (Matches("ALTER", "INDEX"))
2497 "ALL IN TABLESPACE");
2498 /* ALTER INDEX <name> */
2499 else if (Matches("ALTER", "INDEX", MatchAny))
2500 COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
2501 "RESET", "ATTACH PARTITION",
2502 "DEPENDS ON EXTENSION", "NO DEPENDS ON EXTENSION");
2503 else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH"))
2504 COMPLETE_WITH("PARTITION");
2505 else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
2507 /* ALTER INDEX <name> ALTER */
2508 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER"))
2509 COMPLETE_WITH("COLUMN");
2510 /* ALTER INDEX <name> ALTER COLUMN */
2511 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN"))
2512 {
2515 }
2516 /* ALTER INDEX <name> ALTER COLUMN <colnum> */
2517 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
2518 COMPLETE_WITH("SET STATISTICS");
2519 /* ALTER INDEX <name> ALTER COLUMN <colnum> SET */
2520 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET"))
2521 COMPLETE_WITH("STATISTICS");
2522 /* ALTER INDEX <name> ALTER COLUMN <colnum> SET STATISTICS */
2523 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS"))
2524 {
2525 /* Enforce no completion here, as an integer has to be specified */
2526 }
2527 /* ALTER INDEX <name> SET */
2528 else if (Matches("ALTER", "INDEX", MatchAny, "SET"))
2529 COMPLETE_WITH("(", "TABLESPACE");
2530 /* ALTER INDEX <name> RESET */
2531 else if (Matches("ALTER", "INDEX", MatchAny, "RESET"))
2532 COMPLETE_WITH("(");
2533 /* ALTER INDEX <foo> SET|RESET ( */
2534 else if (Matches("ALTER", "INDEX", MatchAny, "RESET", "("))
2535 COMPLETE_WITH("fillfactor",
2536 "deduplicate_items", /* BTREE */
2537 "fastupdate", "gin_pending_list_limit", /* GIN */
2538 "buffering", /* GiST */
2539 "pages_per_range", "autosummarize" /* BRIN */
2540 );
2541 else if (Matches("ALTER", "INDEX", MatchAny, "SET", "("))
2542 COMPLETE_WITH("fillfactor =",
2543 "deduplicate_items =", /* BTREE */
2544 "fastupdate =", "gin_pending_list_limit =", /* GIN */
2545 "buffering =", /* GiST */
2546 "pages_per_range =", "autosummarize =" /* BRIN */
2547 );
2548 else if (Matches("ALTER", "INDEX", MatchAny, "NO", "DEPENDS"))
2549 COMPLETE_WITH("ON EXTENSION");
2550 else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS"))
2551 COMPLETE_WITH("ON EXTENSION");
2552
2553 /* ALTER LANGUAGE <name> */
2554 else if (Matches("ALTER", "LANGUAGE", MatchAny))
2555 COMPLETE_WITH("OWNER TO", "RENAME TO");
2556
2557 /* ALTER LARGE OBJECT <oid> */
2558 else if (Matches("ALTER", "LARGE", "OBJECT", MatchAny))
2559 COMPLETE_WITH("OWNER TO");
2560
2561 /* ALTER MATERIALIZED VIEW */
2562 else if (Matches("ALTER", "MATERIALIZED", "VIEW"))
2564 "ALL IN TABLESPACE");
2565
2566 /* ALTER USER,ROLE <name> */
2567 else if (Matches("ALTER", "USER|ROLE", MatchAny) &&
2568 !TailMatches("USER", "MAPPING"))
2569 COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2570 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2571 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2572 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2573 "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
2574 "VALID UNTIL", "WITH");
2575 /* ALTER USER,ROLE <name> IN */
2576 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN"))
2577 COMPLETE_WITH("DATABASE");
2578 /* ALTER USER,ROLE <name> IN DATABASE */
2579 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE"))
2581 /* ALTER USER,ROLE <name> IN DATABASE <dbname> */
2582 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE", MatchAny))
2583 COMPLETE_WITH("SET", "RESET");
2584 /* ALTER USER,ROLE <name> IN DATABASE <dbname> SET */
2585 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE", MatchAny, "SET"))
2587 /* XXX missing support for ALTER ROLE <name> IN DATABASE <dbname> RESET */
2588 /* ALTER USER,ROLE <name> RESET */
2589 else if (Matches("ALTER", "USER|ROLE", MatchAny, "RESET"))
2590 {
2593 }
2594
2595 /* ALTER USER,ROLE <name> WITH */
2596 else if (Matches("ALTER", "USER|ROLE", MatchAny, "WITH"))
2597 /* Similar to the above, but don't complete "WITH" again. */
2598 COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2599 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
2600 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2601 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2602 "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
2603 "VALID UNTIL");
2604
2605 /* ALTER DEFAULT PRIVILEGES */
2606 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES"))
2607 COMPLETE_WITH("FOR", "GRANT", "IN SCHEMA", "REVOKE");
2608 /* ALTER DEFAULT PRIVILEGES FOR */
2609 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
2610 COMPLETE_WITH("ROLE");
2611 /* ALTER DEFAULT PRIVILEGES IN */
2612 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
2613 COMPLETE_WITH("SCHEMA");
2614 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
2615 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2616 MatchAny))
2617 COMPLETE_WITH("GRANT", "REVOKE", "IN SCHEMA");
2618 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
2619 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2620 MatchAny))
2621 COMPLETE_WITH("GRANT", "REVOKE", "FOR ROLE");
2622 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
2623 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2624 MatchAny, "FOR"))
2625 COMPLETE_WITH("ROLE");
2626 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
2627 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
2628 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2629 MatchAny, "IN", "SCHEMA", MatchAny) ||
2630 Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2631 MatchAny, "FOR", "ROLE|USER", MatchAny))
2632 COMPLETE_WITH("GRANT", "REVOKE");
2633 /* ALTER DOMAIN <name> */
2634 else if (Matches("ALTER", "DOMAIN", MatchAny))
2635 COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME", "SET",
2636 "VALIDATE CONSTRAINT");
2637 /* ALTER DOMAIN <sth> ADD */
2638 else if (Matches("ALTER", "DOMAIN", MatchAny, "ADD"))
2639 COMPLETE_WITH("CONSTRAINT", "NOT NULL", "CHECK (");
2640 /* ALTER DOMAIN <sth> ADD CONSTRAINT <sth> */
2641 else if (Matches("ALTER", "DOMAIN", MatchAny, "ADD", "CONSTRAINT", MatchAny))
2642 COMPLETE_WITH("NOT NULL", "CHECK (");
2643 /* ALTER DOMAIN <sth> DROP */
2644 else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP"))
2645 COMPLETE_WITH("CONSTRAINT", "DEFAULT", "NOT NULL");
2646 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
2647 else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
2648 {
2651 }
2652 /* ALTER DOMAIN <sth> RENAME */
2653 else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME"))
2654 COMPLETE_WITH("CONSTRAINT", "TO");
2655 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
2656 else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
2657 COMPLETE_WITH("TO");
2658
2659 /* ALTER DOMAIN <sth> SET */
2660 else if (Matches("ALTER", "DOMAIN", MatchAny, "SET"))
2661 COMPLETE_WITH("DEFAULT", "NOT NULL", "SCHEMA");
2662 /* ALTER SEQUENCE <name> */
2663 else if (Matches("ALTER", "SEQUENCE", MatchAny))
2664 COMPLETE_WITH("AS", "INCREMENT", "MINVALUE", "MAXVALUE", "RESTART",
2665 "START", "NO", "CACHE", "CYCLE", "SET", "OWNED BY",
2666 "OWNER TO", "RENAME TO");
2667 /* ALTER SEQUENCE <name> AS */
2668 else if (TailMatches("ALTER", "SEQUENCE", MatchAny, "AS"))
2669 COMPLETE_WITH_CS("smallint", "integer", "bigint");
2670 /* ALTER SEQUENCE <name> NO */
2671 else if (Matches("ALTER", "SEQUENCE", MatchAny, "NO"))
2672 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
2673 /* ALTER SEQUENCE <name> SET */
2674 else if (Matches("ALTER", "SEQUENCE", MatchAny, "SET"))
2675 COMPLETE_WITH("SCHEMA", "LOGGED", "UNLOGGED");
2676 /* ALTER SERVER <name> */
2677 else if (Matches("ALTER", "SERVER", MatchAny))
2678 COMPLETE_WITH("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
2679 /* ALTER SERVER <name> VERSION <version> */
2680 else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
2681 COMPLETE_WITH("OPTIONS");
2682 /* ALTER SYSTEM SET, RESET, RESET ALL */
2683 else if (Matches("ALTER", "SYSTEM"))
2684 COMPLETE_WITH("SET", "RESET");
2685 else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
2687 "ALL");
2688 else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
2689 COMPLETE_WITH("TO");
2690 /* ALTER VIEW <name> */
2691 else if (Matches("ALTER", "VIEW", MatchAny))
2692 COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME", "RESET", "SET");
2693 /* ALTER VIEW xxx RENAME */
2694 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME"))
2695 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
2696 else if (Matches("ALTER", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
2698 /* ALTER VIEW xxx ALTER [ COLUMN ] yyy */
2699 else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
2700 Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
2701 COMPLETE_WITH("SET DEFAULT", "DROP DEFAULT");
2702 /* ALTER VIEW xxx RENAME yyy */
2703 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
2704 COMPLETE_WITH("TO");
2705 /* ALTER VIEW xxx RENAME COLUMN yyy */
2706 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
2707 COMPLETE_WITH("TO");
2708 /* ALTER VIEW xxx RESET ( */
2709 else if (Matches("ALTER", "VIEW", MatchAny, "RESET"))
2710 COMPLETE_WITH("(");
2711 /* Complete ALTER VIEW xxx SET with "(" or "SCHEMA" */
2712 else if (Matches("ALTER", "VIEW", MatchAny, "SET"))
2713 COMPLETE_WITH("(", "SCHEMA");
2714 /* ALTER VIEW xxx SET|RESET ( yyy [= zzz] ) */
2715 else if (Matches("ALTER", "VIEW", MatchAny, "SET|RESET", "("))
2717 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", MatchAny))
2718 COMPLETE_WITH("=");
2719 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "check_option", "="))
2720 COMPLETE_WITH("local", "cascaded");
2721 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "security_barrier|security_invoker", "="))
2722 COMPLETE_WITH("true", "false");
2723
2724 /* ALTER MATERIALIZED VIEW <name> */
2725 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
2726 COMPLETE_WITH("ALTER COLUMN", "CLUSTER ON", "DEPENDS ON EXTENSION",
2727 "NO DEPENDS ON EXTENSION", "OWNER TO", "RENAME",
2728 "RESET (", "SET");
2729 /* ALTER MATERIALIZED VIEW xxx RENAME */
2730 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME"))
2731 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
2732 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
2734 /* ALTER MATERIALIZED VIEW xxx RENAME yyy */
2735 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
2736 COMPLETE_WITH("TO");
2737 /* ALTER MATERIALIZED VIEW xxx RENAME COLUMN yyy */
2738 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
2739 COMPLETE_WITH("TO");
2740 /* ALTER MATERIALIZED VIEW xxx SET */
2741 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET"))
2742 COMPLETE_WITH("(", "ACCESS METHOD", "SCHEMA", "TABLESPACE", "WITHOUT CLUSTER");
2743 /* ALTER MATERIALIZED VIEW xxx SET ACCESS METHOD */
2744 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET", "ACCESS", "METHOD"))
2746
2747 /* ALTER POLICY <name> */
2748 else if (Matches("ALTER", "POLICY"))
2750 /* ALTER POLICY <name> ON */
2751 else if (Matches("ALTER", "POLICY", MatchAny))
2752 COMPLETE_WITH("ON");
2753 /* ALTER POLICY <name> ON <table> */
2754 else if (Matches("ALTER", "POLICY", MatchAny, "ON"))
2755 {
2758 }
2759 /* ALTER POLICY <name> ON <table> - show options */
2760 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny))
2761 COMPLETE_WITH("RENAME TO", "TO", "USING (", "WITH CHECK (");
2762 /* ALTER POLICY <name> ON <table> TO <role> */
2763 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2766 /* ALTER POLICY <name> ON <table> USING ( */
2767 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2768 COMPLETE_WITH("(");
2769 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
2770 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
2771 COMPLETE_WITH("(");
2772
2773 /* ALTER PROPERTY GRAPH */
2774 else if (Matches("ALTER", "PROPERTY", "GRAPH"))
2776 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny))
2777 COMPLETE_WITH("ADD", "ALTER", "DROP", "OWNER TO", "RENAME TO", "SET SCHEMA");
2778 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD|ALTER|DROP"))
2779 COMPLETE_WITH("VERTEX", "EDGE");
2780 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD|DROP", "VERTEX|EDGE"))
2781 COMPLETE_WITH("TABLES");
2782 else if (HeadMatches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD") && TailMatches("EDGE"))
2783 COMPLETE_WITH("TABLES");
2784 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ALTER", "VERTEX|EDGE"))
2785 COMPLETE_WITH("TABLE");
2786
2787 /* ALTER RULE <name>, add ON */
2788 else if (Matches("ALTER", "RULE", MatchAny))
2789 COMPLETE_WITH("ON");
2790
2791 /* If we have ALTER RULE <name> ON, then add the correct tablename */
2792 else if (Matches("ALTER", "RULE", MatchAny, "ON"))
2793 {
2796 }
2797
2798 /* ALTER RULE <name> ON <name> */
2799 else if (Matches("ALTER", "RULE", MatchAny, "ON", MatchAny))
2800 COMPLETE_WITH("RENAME TO");
2801
2802 /* ALTER STATISTICS <name> */
2803 else if (Matches("ALTER", "STATISTICS", MatchAny))
2804 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA", "SET STATISTICS");
2805 /* ALTER STATISTICS <name> SET */
2806 else if (Matches("ALTER", "STATISTICS", MatchAny, "SET"))
2807 COMPLETE_WITH("SCHEMA", "STATISTICS");
2808
2809 /* ALTER TRIGGER <name>, add ON */
2810 else if (Matches("ALTER", "TRIGGER", MatchAny))
2811 COMPLETE_WITH("ON");
2812
2813 else if (Matches("ALTER", "TRIGGER", MatchAny, "ON"))
2814 {
2817 }
2818
2819 /* ALTER TRIGGER <name> ON <name> */
2820 else if (Matches("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
2821 COMPLETE_WITH("RENAME TO", "DEPENDS ON EXTENSION",
2822 "NO DEPENDS ON EXTENSION");
2823
2824 /*
2825 * If we detect ALTER TABLE <name>, suggest sub commands
2826 */
2827 else if (Matches("ALTER", "TABLE", MatchAny))
2828 COMPLETE_WITH("ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP",
2829 "ENABLE", "INHERIT", "NO", "RENAME", "RESET",
2830 "OWNER TO", "SET", "VALIDATE CONSTRAINT",
2831 "REPLICA IDENTITY", "ATTACH PARTITION",
2832 "DETACH PARTITION", "FORCE ROW LEVEL SECURITY",
2833 "SPLIT PARTITION", "MERGE PARTITIONS (",
2834 "OF", "NOT OF");
2835 /* ALTER TABLE xxx ADD */
2836 else if (Matches("ALTER", "TABLE", MatchAny, "ADD"))
2837 {
2838 /*
2839 * make sure to keep this list and the MatchAnyExcept() below in sync
2840 */
2841 COMPLETE_WITH("COLUMN", "CONSTRAINT", "CHECK (", "NOT NULL", "UNIQUE",
2842 "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
2843 }
2844 /* ALTER TABLE xxx ADD [COLUMN] yyy */
2845 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN", MatchAny) ||
2846 Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAnyExcept("COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|NOT|EXCLUDE|FOREIGN")))
2848 /* ALTER TABLE xxx ADD CONSTRAINT yyy */
2849 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny))
2850 COMPLETE_WITH("CHECK (", "NOT NULL", "UNIQUE", "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
2851 /* ALTER TABLE xxx ADD NOT NULL */
2852 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "NOT", "NULL"))
2854 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "NOT", "NULL"))
2856 /* ALTER TABLE xxx ADD [CONSTRAINT yyy] (PRIMARY KEY|UNIQUE) */
2857 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY") ||
2858 Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE") ||
2859 Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "PRIMARY", "KEY") ||
2860 Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "UNIQUE"))
2861 COMPLETE_WITH("(", "USING INDEX");
2862 /* ALTER TABLE xxx ADD PRIMARY KEY USING INDEX */
2863 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY", "USING", "INDEX"))
2864 {
2867 }
2868 /* ALTER TABLE xxx ADD UNIQUE USING INDEX */
2869 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE", "USING", "INDEX"))
2870 {
2873 }
2874 /* ALTER TABLE xxx ADD CONSTRAINT yyy PRIMARY KEY USING INDEX */
2875 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2876 "PRIMARY", "KEY", "USING", "INDEX"))
2877 {
2880 }
2881 /* ALTER TABLE xxx ADD CONSTRAINT yyy UNIQUE USING INDEX */
2882 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2883 "UNIQUE", "USING", "INDEX"))
2884 {
2887 }
2888 /* ALTER TABLE xxx ENABLE */
2889 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE"))
2890 COMPLETE_WITH("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
2891 "TRIGGER");
2892 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
2893 COMPLETE_WITH("RULE", "TRIGGER");
2894 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
2895 {
2898 }
2899 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
2900 {
2903 }
2904 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
2905 {
2908 }
2909 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
2910 {
2913 }
2914 /* ALTER TABLE xxx INHERIT */
2915 else if (Matches("ALTER", "TABLE", MatchAny, "INHERIT"))
2917 /* ALTER TABLE xxx NO */
2918 else if (Matches("ALTER", "TABLE", MatchAny, "NO"))
2919 COMPLETE_WITH("FORCE ROW LEVEL SECURITY", "INHERIT");
2920 /* ALTER TABLE xxx NO INHERIT */
2921 else if (Matches("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
2923 /* ALTER TABLE xxx DISABLE */
2924 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE"))
2925 COMPLETE_WITH("ROW LEVEL SECURITY", "RULE", "TRIGGER");
2926 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
2927 {
2930 }
2931 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
2932 {
2935 }
2936
2937 /* ALTER TABLE xxx ALTER */
2938 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER"))
2939 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT");
2940
2941 /* ALTER TABLE xxx RENAME */
2942 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME"))
2943 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT", "TO");
2944 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
2946
2947 /* ALTER TABLE xxx RENAME yyy */
2948 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
2949 COMPLETE_WITH("TO");
2950
2951 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
2952 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
2953 COMPLETE_WITH("TO");
2954
2955 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
2956 else if (Matches("ALTER", "TABLE", MatchAny, "DROP"))
2957 COMPLETE_WITH("COLUMN", "CONSTRAINT");
2958 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
2959 else if (Matches("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
2961 /* ALTER TABLE <sth> ALTER|DROP|RENAME CONSTRAINT <constraint> */
2962 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME", "CONSTRAINT"))
2963 {
2966 }
2967 /* ALTER TABLE <sth> VALIDATE CONSTRAINT <non-validated constraint> */
2968 else if (Matches("ALTER", "TABLE", MatchAny, "VALIDATE", "CONSTRAINT"))
2969 {
2972 }
2973 /* ALTER TABLE ALTER [COLUMN] <foo> */
2974 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
2975 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
2976 COMPLETE_WITH("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
2977 /* ALTER TABLE ALTER [COLUMN] <foo> ADD */
2978 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD") ||
2979 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD"))
2980 COMPLETE_WITH("GENERATED");
2981 /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
2982 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED") ||
2983 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED"))
2984 COMPLETE_WITH("ALWAYS", "BY DEFAULT");
2985 /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
2986 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2987 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2988 Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT") ||
2989 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT"))
2990 COMPLETE_WITH("AS IDENTITY");
2991 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
2992 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
2993 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
2994 COMPLETE_WITH("(", "COMPRESSION", "DATA TYPE", "DEFAULT", "EXPRESSION", "GENERATED", "NOT NULL",
2995 "STATISTICS", "STORAGE",
2996 /* a subset of ALTER SEQUENCE options */
2997 "INCREMENT", "MINVALUE", "MAXVALUE", "START", "NO", "CACHE", "CYCLE");
2998 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
2999 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
3000 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
3001 COMPLETE_WITH("n_distinct", "n_distinct_inherited");
3002 /* ALTER TABLE ALTER [COLUMN] <foo> SET COMPRESSION */
3003 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "COMPRESSION") ||
3004 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "COMPRESSION"))
3005 COMPLETE_WITH("DEFAULT", "PGLZ", "LZ4");
3006 /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION */
3007 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION") ||
3008 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION"))
3009 COMPLETE_WITH("AS");
3010 /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION AS */
3011 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION", "AS") ||
3012 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION", "AS"))
3013 COMPLETE_WITH("(");
3014 /* ALTER TABLE ALTER [COLUMN] <foo> SET GENERATED */
3015 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "GENERATED") ||
3016 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "GENERATED"))
3017 COMPLETE_WITH("ALWAYS", "BY DEFAULT");
3018 /* ALTER TABLE ALTER [COLUMN] <foo> SET NO */
3019 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "NO") ||
3020 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "NO"))
3021 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
3022 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
3023 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
3024 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
3025 COMPLETE_WITH("DEFAULT", "PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
3026 /* ALTER TABLE ALTER [COLUMN] <foo> SET STATISTICS */
3027 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS") ||
3028 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STATISTICS"))
3029 {
3030 /* Enforce no completion here, as an integer has to be specified */
3031 }
3032 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
3033 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
3034 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
3035 COMPLETE_WITH("DEFAULT", "EXPRESSION", "IDENTITY", "NOT NULL");
3036 else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER"))
3037 COMPLETE_WITH("ON");
3038 else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
3039 {
3042 }
3043 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
3044 else if (Matches("ALTER", "TABLE", MatchAny, "SET"))
3045 COMPLETE_WITH("(", "ACCESS METHOD", "LOGGED", "SCHEMA",
3046 "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT");
3047
3048 /*
3049 * If we have ALTER TABLE <sth> SET ACCESS METHOD provide a list of table
3050 * AMs.
3051 */
3052 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "ACCESS", "METHOD"))
3054 "DEFAULT");
3055
3056 /*
3057 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
3058 * tablespaces
3059 */
3060 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
3062 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
3063 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
3064 COMPLETE_WITH("CLUSTER", "OIDS");
3065 /* ALTER TABLE <foo> RESET */
3066 else if (Matches("ALTER", "TABLE", MatchAny, "RESET"))
3067 COMPLETE_WITH("(");
3068 /* ALTER TABLE <foo> SET|RESET ( */
3069 else if (Matches("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
3071 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
3072 {
3075 }
3076 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
3077 COMPLETE_WITH("INDEX");
3078 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
3079 COMPLETE_WITH("FULL", "NOTHING", "DEFAULT", "USING");
3080 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA"))
3081 COMPLETE_WITH("IDENTITY");
3082
3083 /*
3084 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
3085 * tables.
3086 */
3087 else if (Matches("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
3089 /* Limited completion support for partition bound specification */
3090 else if (TailMatches("ATTACH", "PARTITION", MatchAny))
3091 COMPLETE_WITH("FOR VALUES", "DEFAULT");
3092 else if (TailMatches("FOR", "VALUES"))
3093 COMPLETE_WITH("FROM (", "IN (", "WITH (");
3094
3095 /*
3096 * If we have ALTER TABLE <foo> DETACH|SPLIT PARTITION, provide a list of
3097 * partitions of <foo>.
3098 */
3099 else if (Matches("ALTER", "TABLE", MatchAny, "DETACH|SPLIT", "PARTITION"))
3100 {
3103 }
3104 else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION", MatchAny))
3105 COMPLETE_WITH("CONCURRENTLY", "FINALIZE");
3106
3107 /* ALTER TABLE <name> SPLIT PARTITION <name> */
3108 else if (Matches("ALTER", "TABLE", MatchAny, "SPLIT", "PARTITION", MatchAny))
3109 COMPLETE_WITH("INTO ( PARTITION");
3110
3111 /* ALTER TABLE <name> MERGE PARTITIONS ( */
3112 else if (Matches("ALTER", "TABLE", MatchAny, "MERGE", "PARTITIONS", "("))
3113 {
3116 }
3117 else if (Matches("ALTER", "TABLE", MatchAny, "MERGE", "PARTITIONS", "(*)"))
3118 COMPLETE_WITH("INTO");
3119
3120 /* ALTER TABLE <name> OF */
3121 else if (Matches("ALTER", "TABLE", MatchAny, "OF"))
3123
3124 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
3125 else if (Matches("ALTER", "TABLESPACE", MatchAny))
3126 COMPLETE_WITH("RENAME TO", "OWNER TO", "SET", "RESET");
3127 /* ALTER TABLESPACE <foo> SET|RESET */
3128 else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
3129 COMPLETE_WITH("(");
3130 /* ALTER TABLESPACE <foo> SET|RESET ( */
3131 else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
3132 COMPLETE_WITH("seq_page_cost", "random_page_cost",
3133 "effective_io_concurrency", "maintenance_io_concurrency");
3134
3135 /* ALTER TEXT SEARCH */
3136 else if (Matches("ALTER", "TEXT", "SEARCH"))
3137 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3138 else if (Matches("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
3139 COMPLETE_WITH("RENAME TO", "SET SCHEMA");
3140 else if (Matches("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
3141 COMPLETE_WITH("(", "OWNER TO", "RENAME TO", "SET SCHEMA");
3142 else if (Matches("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
3143 COMPLETE_WITH("ADD MAPPING FOR", "ALTER MAPPING",
3144 "DROP MAPPING FOR",
3145 "OWNER TO", "RENAME TO", "SET SCHEMA");
3146
3147 /* complete ALTER TYPE <foo> with actions */
3148 else if (Matches("ALTER", "TYPE", MatchAny))
3149 COMPLETE_WITH("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
3150 "DROP ATTRIBUTE",
3151 "OWNER TO", "RENAME", "SET SCHEMA", "SET (");
3152 /* complete ALTER TYPE <foo> ADD with actions */
3153 else if (Matches("ALTER", "TYPE", MatchAny, "ADD"))
3154 COMPLETE_WITH("ATTRIBUTE", "VALUE");
3155 /* ALTER TYPE <foo> RENAME */
3156 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME"))
3157 COMPLETE_WITH("ATTRIBUTE", "TO", "VALUE");
3158 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
3159 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
3160 COMPLETE_WITH("TO");
3161 /* ALTER TYPE xxx RENAME ATTRIBUTE yyy TO zzz */
3162 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny, "TO", MatchAny))
3163 COMPLETE_WITH("CASCADE", "RESTRICT");
3164
3165 /*
3166 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
3167 * of attributes
3168 */
3169 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
3171 /* complete ALTER TYPE ADD ATTRIBUTE <foo> with list of types */
3172 else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny))
3174 /* complete ALTER TYPE ADD ATTRIBUTE <foo> <footype> with CASCADE/RESTRICT */
3175 else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny, MatchAny))
3176 COMPLETE_WITH("CASCADE", "RESTRICT");
3177 /* complete ALTER TYPE DROP ATTRIBUTE <foo> with CASCADE/RESTRICT */
3178 else if (Matches("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE", MatchAny))
3179 COMPLETE_WITH("CASCADE", "RESTRICT");
3180 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
3181 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
3182 COMPLETE_WITH("TYPE");
3183 /* ALTER TYPE ALTER ATTRIBUTE <foo> TYPE <footype> */
3184 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny, "TYPE", MatchAny))
3185 COMPLETE_WITH("CASCADE", "RESTRICT");
3186 /* complete ALTER TYPE <sth> RENAME VALUE with list of enum values */
3187 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
3189 /* ALTER TYPE <foo> SET */
3190 else if (Matches("ALTER", "TYPE", MatchAny, "SET"))
3191 COMPLETE_WITH("(", "SCHEMA");
3192 /* complete ALTER TYPE <foo> SET ( with settable properties */
3193 else if (Matches("ALTER", "TYPE", MatchAny, "SET", "("))
3194 COMPLETE_WITH("ANALYZE", "RECEIVE", "SEND", "STORAGE", "SUBSCRIPT",
3195 "TYPMOD_IN", "TYPMOD_OUT");
3196
3197 /* complete ALTER GROUP <foo> */
3198 else if (Matches("ALTER", "GROUP", MatchAny))
3199 COMPLETE_WITH("ADD USER", "DROP USER", "RENAME TO");
3200 /* complete ALTER GROUP <foo> ADD|DROP with USER */
3201 else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP"))
3202 COMPLETE_WITH("USER");
3203 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
3204 else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
3206
3207/*
3208 * ANALYZE [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
3209 * ANALYZE [ VERBOSE ] [ [ ONLY ] table_and_columns [, ...] ]
3210 */
3211 else if (Matches("ANALYZE"))
3213 "(", "VERBOSE", "ONLY");
3214 else if (Matches("ANALYZE", "VERBOSE"))
3216 "ONLY");
3217 else if (HeadMatches("ANALYZE", "(*") &&
3218 !HeadMatches("ANALYZE", "(*)"))
3219 {
3220 /*
3221 * This fires if we're in an unfinished parenthesized option list.
3222 * get_previous_words treats a completed parenthesized option list as
3223 * one word, so the above test is correct.
3224 */
3225 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3226 COMPLETE_WITH("VERBOSE", "SKIP_LOCKED", "BUFFER_USAGE_LIMIT");
3227 else if (TailMatches("VERBOSE|SKIP_LOCKED"))
3228 COMPLETE_WITH("ON", "OFF");
3229 }
3230 else if (Matches("ANALYZE", "(*)"))
3232 "ONLY");
3233 else if (Matches("ANALYZE", MatchAnyN, "("))
3234 /* "ANALYZE (" should be caught above, so assume we want columns */
3236 else if (HeadMatches("ANALYZE"))
3238
3239/* BEGIN */
3240 else if (Matches("BEGIN"))
3241 COMPLETE_WITH("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3242/* END, ABORT */
3243 else if (Matches("END|ABORT"))
3244 COMPLETE_WITH("AND", "WORK", "TRANSACTION");
3245/* COMMIT */
3246 else if (Matches("COMMIT"))
3247 COMPLETE_WITH("AND", "WORK", "TRANSACTION", "PREPARED");
3248/* RELEASE SAVEPOINT */
3249 else if (Matches("RELEASE"))
3250 COMPLETE_WITH("SAVEPOINT");
3251/* ROLLBACK */
3252 else if (Matches("ROLLBACK"))
3253 COMPLETE_WITH("AND", "WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
3254 else if (Matches("ABORT|END|COMMIT|ROLLBACK", "AND"))
3255 COMPLETE_WITH("CHAIN");
3256/* CALL */
3257 else if (Matches("CALL"))
3259 else if (Matches("CALL", MatchAny))
3260 COMPLETE_WITH("(");
3261/* CHECKPOINT */
3262 else if (Matches("CHECKPOINT"))
3263 COMPLETE_WITH("(");
3264 else if (HeadMatches("CHECKPOINT", "(*") &&
3265 !HeadMatches("CHECKPOINT", "(*)"))
3266 {
3267 /*
3268 * This fires if we're in an unfinished parenthesized option list.
3269 * get_previous_words treats a completed parenthesized option list as
3270 * one word, so the above test is correct.
3271 */
3272 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3273 COMPLETE_WITH("MODE", "FLUSH_UNLOGGED");
3274 else if (TailMatches("MODE"))
3275 COMPLETE_WITH("FAST", "SPREAD");
3276 }
3277/* CLOSE */
3278 else if (Matches("CLOSE"))
3280 "ALL");
3281/* CLUSTER */
3282 else if (Matches("CLUSTER"))
3284 "VERBOSE");
3285 else if (Matches("CLUSTER", "VERBOSE") ||
3286 Matches("CLUSTER", "(*)"))
3288 /* If we have CLUSTER <sth>, then add "USING" */
3289 else if (Matches("CLUSTER", MatchAnyExcept("VERBOSE|ON|(|(*)")))
3290 COMPLETE_WITH("USING");
3291 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
3292 else if (Matches("CLUSTER", "VERBOSE|(*)", MatchAny))
3293 COMPLETE_WITH("USING");
3294 /* If we have CLUSTER <sth> USING, then add the index as well */
3295 else if (Matches("CLUSTER", MatchAny, "USING") ||
3296 Matches("CLUSTER", "VERBOSE|(*)", MatchAny, "USING"))
3297 {
3300 }
3301 else if (HeadMatches("CLUSTER", "(*") &&
3302 !HeadMatches("CLUSTER", "(*)"))
3303 {
3304 /*
3305 * This fires if we're in an unfinished parenthesized option list.
3306 * get_previous_words treats a completed parenthesized option list as
3307 * one word, so the above test is correct.
3308 */
3309 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3310 COMPLETE_WITH("VERBOSE");
3311 }
3312
3313/* COMMENT */
3314 else if (Matches("COMMENT"))
3315 COMPLETE_WITH("ON");
3316 else if (Matches("COMMENT", "ON"))
3317 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
3318 "COLUMN", "CONSTRAINT", "CONVERSION", "DATABASE",
3319 "DOMAIN", "EXTENSION", "EVENT TRIGGER",
3320 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
3321 "FUNCTION", "INDEX", "LANGUAGE", "LARGE OBJECT",
3322 "MATERIALIZED VIEW", "OPERATOR", "POLICY",
3323 "PROCEDURE", "PROCEDURAL LANGUAGE", "PROPERTY GRAPH", "PUBLICATION", "ROLE",
3324 "ROUTINE", "RULE", "SCHEMA", "SEQUENCE", "SERVER",
3325 "STATISTICS", "SUBSCRIPTION", "TABLE",
3326 "TABLESPACE", "TEXT SEARCH", "TRANSFORM FOR",
3327 "TRIGGER", "TYPE", "VIEW");
3328 else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
3330 else if (Matches("COMMENT", "ON", "CONSTRAINT"))
3332 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny))
3333 COMPLETE_WITH("ON");
3334 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
3335 {
3338 "DOMAIN");
3339 }
3340 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON", "DOMAIN"))
3342 else if (Matches("COMMENT", "ON", "EVENT", "TRIGGER"))
3344 else if (Matches("COMMENT", "ON", "FOREIGN"))
3345 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3346 else if (Matches("COMMENT", "ON", "FOREIGN", "TABLE"))
3348 else if (Matches("COMMENT", "ON", "MATERIALIZED", "VIEW"))
3350 else if (Matches("COMMENT", "ON", "POLICY"))
3352 else if (Matches("COMMENT", "ON", "POLICY", MatchAny))
3353 COMPLETE_WITH("ON");
3354 else if (Matches("COMMENT", "ON", "POLICY", MatchAny, "ON"))
3355 {
3358 }
3359 else if (Matches("COMMENT", "ON", "PROCEDURAL", "LANGUAGE"))
3361 else if (Matches("COMMENT", "ON", "PROPERTY", "GRAPH"))
3363 else if (Matches("COMMENT", "ON", "RULE", MatchAny))
3364 COMPLETE_WITH("ON");
3365 else if (Matches("COMMENT", "ON", "RULE", MatchAny, "ON"))
3366 {
3369 }
3370 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH"))
3371 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3372 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "CONFIGURATION"))
3374 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "DICTIONARY"))
3376 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "PARSER"))
3378 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "TEMPLATE"))
3380 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR"))
3382 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny))
3383 COMPLETE_WITH("LANGUAGE");
3384 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3385 {
3388 }
3389 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny))
3390 COMPLETE_WITH("ON");
3391 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny, "ON"))
3392 {
3395 }
3396 else if (Matches("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
3397 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3398 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3399 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
3400 COMPLETE_WITH("IS");
3401
3402/* COPY */
3403
3404 /*
3405 * If we have COPY, offer list of tables or "(" (Also cover the analogous
3406 * backslash command).
3407 */
3408 else if (Matches("COPY|\\copy"))
3410 /* Complete COPY ( with legal query commands */
3411 else if (Matches("COPY|\\copy", "("))
3412 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "MERGE INTO", "WITH");
3413 /* Complete COPY <sth> */
3414 else if (Matches("COPY|\\copy", MatchAny))
3415 COMPLETE_WITH("FROM", "TO");
3416 /* Complete COPY|\copy <sth> FROM|TO with filename or STDIN/STDOUT/PROGRAM */
3417 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO"))
3418 {
3419 if (HeadMatches("COPY"))
3420 {
3421 /* COPY requires quoted filename */
3422 if (TailMatches("FROM"))
3423 COMPLETE_WITH_FILES_PLUS("", true, "STDIN", "PROGRAM");
3424 else
3425 COMPLETE_WITH_FILES_PLUS("", true, "STDOUT", "PROGRAM");
3426 }
3427 else
3428 {
3429 /* \copy supports pstdin and pstdout */
3430 if (TailMatches("FROM"))
3431 COMPLETE_WITH_FILES_PLUS("", false, "STDIN", "PSTDIN", "PROGRAM");
3432 else
3433 COMPLETE_WITH_FILES_PLUS("", false, "STDOUT", "PSTDOUT", "PROGRAM");
3434 }
3435 }
3436
3437 /* Complete COPY|\copy <sth> FROM|TO PROGRAM */
3438 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM"))
3439 COMPLETE_WITH_FILES("", HeadMatches("COPY")); /* COPY requires quoted
3440 * filename */
3441
3442 /* Complete COPY <sth> TO [PROGRAM] <sth> */
3443 else if (Matches("COPY|\\copy", MatchAny, "TO", MatchAnyExcept("PROGRAM")) ||
3444 Matches("COPY|\\copy", MatchAny, "TO", "PROGRAM", MatchAny))
3445 COMPLETE_WITH("WITH (");
3446
3447 /* Complete COPY <sth> FROM [PROGRAM] <sth> */
3448 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM")) ||
3449 Matches("COPY|\\copy", MatchAny, "FROM", "PROGRAM", MatchAny))
3450 COMPLETE_WITH("WITH (", "WHERE");
3451
3452 /* Complete COPY <sth> FROM|TO [PROGRAM] filename WITH ( */
3453 else if (HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*") ||
3454 HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*"))
3455 {
3456 if (!HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*)") &&
3457 !HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*)"))
3458 {
3459 /*
3460 * This fires if we're in an unfinished parenthesized option list.
3461 * get_previous_words treats a completed parenthesized option list
3462 * as one word, so the above tests are correct.
3463 */
3464
3465 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3466 {
3467 if (HeadMatches("COPY|\\copy", MatchAny, "FROM"))
3469 else
3471 }
3472
3473 /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
3474 else if (TailMatches("FORMAT"))
3475 COMPLETE_WITH("binary", "csv", "text", "json");
3476
3477 /* Complete COPY <sth> FROM|TO filename WITH (FREEZE */
3478 else if (TailMatches("FREEZE"))
3479 COMPLETE_WITH("true", "false");
3480
3481 /* Complete COPY <sth> FROM|TO filename WITH (HEADER */
3482 else if (TailMatches("HEADER"))
3483 COMPLETE_WITH("true", "false", "MATCH");
3484
3485 /* Complete COPY <sth> FROM filename WITH (ON_ERROR */
3486 else if (TailMatches("ON_ERROR"))
3487 COMPLETE_WITH("stop", "ignore", "set_null");
3488
3489 /* Complete COPY <sth> FROM filename WITH (LOG_VERBOSITY */
3490 else if (TailMatches("LOG_VERBOSITY"))
3491 COMPLETE_WITH("silent", "default", "verbose");
3492 }
3493
3494 /* A completed parenthesized option list should be caught below */
3495 }
3496
3497 /* Complete COPY <sth> FROM [PROGRAM] <sth> WITH (<options>) */
3498 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM"), "WITH", MatchAny) ||
3499 Matches("COPY|\\copy", MatchAny, "FROM", "PROGRAM", MatchAny, "WITH", MatchAny))
3500 COMPLETE_WITH("WHERE");
3501
3502 /* CREATE ACCESS METHOD */
3503 /* Complete "CREATE ACCESS METHOD <name>" */
3504 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny))
3505 COMPLETE_WITH("TYPE");
3506 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
3507 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
3508 COMPLETE_WITH("INDEX", "TABLE");
3509 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
3510 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
3511 COMPLETE_WITH("HANDLER");
3512
3513 /* CREATE COLLATION */
3514 else if (Matches("CREATE", "COLLATION", MatchAny))
3515 COMPLETE_WITH("(", "FROM");
3516 else if (Matches("CREATE", "COLLATION", MatchAny, "FROM"))
3518 else if (HeadMatches("CREATE", "COLLATION", MatchAny, "(*"))
3519 {
3520 if (TailMatches("(|*,"))
3521 COMPLETE_WITH("LOCALE =", "LC_COLLATE =", "LC_CTYPE =",
3522 "PROVIDER =", "DETERMINISTIC =");
3523 else if (TailMatches("PROVIDER", "="))
3524 COMPLETE_WITH("libc", "icu");
3525 else if (TailMatches("DETERMINISTIC", "="))
3526 COMPLETE_WITH("true", "false");
3527 }
3528
3529 /* CREATE DATABASE */
3530 else if (Matches("CREATE", "DATABASE", MatchAny))
3531 COMPLETE_WITH("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
3532 "IS_TEMPLATE", "STRATEGY",
3533 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
3534 "LC_COLLATE", "LC_CTYPE", "LOCALE", "OID",
3535 "LOCALE_PROVIDER", "ICU_LOCALE");
3536
3537 else if (Matches("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
3539 else if (Matches("CREATE", "DATABASE", MatchAny, "STRATEGY"))
3540 COMPLETE_WITH("WAL_LOG", "FILE_COPY");
3541
3542 /* CREATE DOMAIN --- is allowed inside CREATE SCHEMA, so use TailMatches */
3543 else if (TailMatches("CREATE", "DOMAIN", MatchAny))
3544 COMPLETE_WITH("AS");
3545 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "AS"))
3547 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
3548 COMPLETE_WITH("COLLATE", "DEFAULT", "CONSTRAINT",
3549 "NOT NULL", "NULL", "CHECK (");
3550 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
3552
3553 /* CREATE EXTENSION */
3554 /* Complete with available extensions rather than installed ones. */
3555 else if (Matches("CREATE", "EXTENSION"))
3557 /* CREATE EXTENSION <name> */
3558 else if (Matches("CREATE", "EXTENSION", MatchAny))
3559 COMPLETE_WITH("WITH SCHEMA", "CASCADE", "VERSION");
3560 /* CREATE EXTENSION <name> VERSION */
3561 else if (Matches("CREATE", "EXTENSION", MatchAny, "VERSION"))
3562 {
3565 }
3566
3567 /* CREATE FOREIGN */
3568 else if (Matches("CREATE", "FOREIGN"))
3569 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3570
3571 /* CREATE FOREIGN DATA WRAPPER */
3572 else if (Matches("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
3573 COMPLETE_WITH("CONNECTION", "HANDLER", "OPTIONS", "VALIDATOR");
3574
3575 /* CREATE FOREIGN TABLE */
3576 else if (Matches("CREATE", "FOREIGN", "TABLE", MatchAny))
3577 COMPLETE_WITH("(", "PARTITION OF");
3578
3579 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
3580 /* First off we complete CREATE UNIQUE with "INDEX" */
3581 else if (TailMatches("CREATE", "UNIQUE"))
3582 COMPLETE_WITH("INDEX");
3583
3584 /*
3585 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
3586 * existing indexes
3587 */
3588 else if (TailMatches("CREATE|UNIQUE", "INDEX"))
3590 "ON", "CONCURRENTLY");
3591
3592 /*
3593 * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
3594 * that indexes can be created on
3595 */
3596 else if (TailMatches("INDEX|CONCURRENTLY", MatchAny, "ON") ||
3597 TailMatches("INDEX|CONCURRENTLY", "ON"))
3599
3600 /*
3601 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
3602 * indexes
3603 */
3604 else if (TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
3606 "ON");
3607 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
3608 else if (TailMatches("CREATE|UNIQUE", "INDEX", MatchAny) ||
3609 TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
3610 COMPLETE_WITH("ON");
3611
3612 /*
3613 * Complete INDEX <name> ON <table> with a list of table columns (which
3614 * should really be in parens)
3615 */
3616 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny) ||
3617 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny))
3618 COMPLETE_WITH("(", "USING");
3619 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny, "(") ||
3620 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
3622 /* same if you put in USING */
3623 else if (TailMatches("ON", MatchAny, "USING", MatchAny, "("))
3625 /* Complete USING with an index method */
3626 else if (TailMatches("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
3627 TailMatches("INDEX", MatchAny, "ON", MatchAny, "USING") ||
3628 TailMatches("INDEX", "ON", MatchAny, "USING"))
3630 else if (TailMatches("ON", MatchAny, "USING", MatchAny) &&
3633 COMPLETE_WITH("(");
3634
3635 /* CREATE OR REPLACE */
3636 else if (Matches("CREATE", "OR"))
3637 COMPLETE_WITH("REPLACE");
3638
3639 /* CREATE POLICY */
3640 /* Complete "CREATE POLICY <name> ON" */
3641 else if (Matches("CREATE", "POLICY", MatchAny))
3642 COMPLETE_WITH("ON");
3643 /* Complete "CREATE POLICY <name> ON <table>" */
3644 else if (Matches("CREATE", "POLICY", MatchAny, "ON"))
3646 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
3647 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny))
3648 COMPLETE_WITH("AS", "FOR", "TO", "USING (", "WITH CHECK (");
3649 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
3650 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
3651 COMPLETE_WITH("PERMISSIVE", "RESTRICTIVE");
3652
3653 /*
3654 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3655 * FOR|TO|USING|WITH CHECK
3656 */
3657 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
3658 COMPLETE_WITH("FOR", "TO", "USING", "WITH CHECK");
3659 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
3660 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
3661 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3662 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
3663 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
3664 COMPLETE_WITH("TO", "WITH CHECK (");
3665 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
3666 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
3667 COMPLETE_WITH("TO", "USING (");
3668 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
3669 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
3670 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3671 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
3672 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
3675 /* Complete "CREATE POLICY <name> ON <table> USING (" */
3676 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
3677 COMPLETE_WITH("(");
3678
3679 /*
3680 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3681 * ALL|SELECT|INSERT|UPDATE|DELETE
3682 */
3683 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
3684 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3685
3686 /*
3687 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3688 * INSERT TO|WITH CHECK"
3689 */
3690 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
3691 COMPLETE_WITH("TO", "WITH CHECK (");
3692
3693 /*
3694 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3695 * SELECT|DELETE TO|USING"
3696 */
3697 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
3698 COMPLETE_WITH("TO", "USING (");
3699
3700 /*
3701 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3702 * ALL|UPDATE TO|USING|WITH CHECK
3703 */
3704 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
3705 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3706
3707 /*
3708 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
3709 * <role>"
3710 */
3711 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
3714
3715 /*
3716 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3717 * USING ("
3718 */
3719 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
3720 COMPLETE_WITH("(");
3721
3722/* CREATE PROPERTY GRAPH */
3723 else if (Matches("CREATE", "PROPERTY"))
3724 COMPLETE_WITH("GRAPH");
3725 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny))
3726 COMPLETE_WITH("VERTEX");
3727 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE"))
3728 COMPLETE_WITH("TABLES");
3729 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES"))
3730 COMPLETE_WITH("(");
3731 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES", "("))
3733 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES", "(*)"))
3734 COMPLETE_WITH("EDGE");
3735 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP"))
3736 COMPLETE_WITH("TABLES");
3737 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP", "TABLES"))
3738 COMPLETE_WITH("(");
3739 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP", "TABLES", "("))
3741
3742/* CREATE PUBLICATION */
3743 else if (Matches("CREATE", "PUBLICATION", MatchAny))
3744 COMPLETE_WITH("FOR TABLE", "FOR TABLES IN SCHEMA", "FOR ALL TABLES", "FOR ALL SEQUENCES", "WITH (");
3745 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
3746 COMPLETE_WITH("TABLE", "TABLES IN SCHEMA", "ALL TABLES", "ALL SEQUENCES");
3747 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL"))
3748 COMPLETE_WITH("TABLES", "SEQUENCES");
3749 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
3750 COMPLETE_WITH("EXCEPT ( TABLE", "WITH (");
3751 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT"))
3752 COMPLETE_WITH("( TABLE");
3753 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "("))
3754 COMPLETE_WITH("TABLE");
3755 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE"))
3757 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd, ','))
3759 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd, ','))
3760 COMPLETE_WITH(")");
3761 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES"))
3762 COMPLETE_WITH("IN SCHEMA");
3763 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) && !ends_with(prev_wd, ','))
3764 COMPLETE_WITH("WHERE (", "WITH (");
3765 /* Complete "CREATE PUBLICATION <name> FOR TABLE" with "<table>, ..." */
3766 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE"))
3768
3769 /*
3770 * "CREATE PUBLICATION <name> FOR TABLE <name> WHERE (" - complete with
3771 * table attributes
3772 */
3773 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE"))
3774 COMPLETE_WITH("(");
3775 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "("))
3777 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "(*)"))
3778 COMPLETE_WITH(" WITH (");
3779
3780 /*
3781 * Complete "CREATE PUBLICATION <name> FOR TABLES IN SCHEMA <schema>, ..."
3782 */
3783 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA"))
3785 " AND nspname NOT LIKE E'pg\\\\_%%'",
3786 "CURRENT_SCHEMA");
3787 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA", MatchAny) && (!ends_with(prev_wd, ',')))
3788 COMPLETE_WITH("WITH (");
3789 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
3790 else if (Matches("CREATE", "PUBLICATION", MatchAnyN, "WITH", "("))
3791 COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root");
3792
3793/* CREATE RULE */
3794 /* Complete "CREATE [ OR REPLACE ] RULE <sth>" with "AS ON" */
3795 else if (Matches("CREATE", "RULE", MatchAny) ||
3796 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny))
3797 COMPLETE_WITH("AS ON");
3798 /* Complete "CREATE [ OR REPLACE ] RULE <sth> AS" with "ON" */
3799 else if (Matches("CREATE", "RULE", MatchAny, "AS") ||
3800 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS"))
3801 COMPLETE_WITH("ON");
3802
3803 /*
3804 * Complete "CREATE [ OR REPLACE ] RULE <sth> AS ON" with
3805 * SELECT|UPDATE|INSERT|DELETE
3806 */
3807 else if (Matches("CREATE", "RULE", MatchAny, "AS", "ON") ||
3808 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS", "ON"))
3809 COMPLETE_WITH("SELECT", "UPDATE", "INSERT", "DELETE");
3810 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
3811 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
3812 COMPLETE_WITH("TO");
3813 /* Complete "AS ON <sth> TO" with a table name */
3814 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
3816
3817/* CREATE SCHEMA [ <name> ] [ AUTHORIZATION ] */
3818 else if (Matches("CREATE", "SCHEMA"))
3820 "AUTHORIZATION");
3821 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION") ||
3822 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION"))
3825 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION", MatchAny) ||
3826 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION", MatchAny))
3827 COMPLETE_WITH("CREATE", "GRANT");
3828 else if (Matches("CREATE", "SCHEMA", MatchAny))
3829 COMPLETE_WITH("AUTHORIZATION", "CREATE", "GRANT");
3830
3831/* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3832 else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
3833 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
3834 COMPLETE_WITH("AS", "INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
3835 "CACHE", "CYCLE", "OWNED BY", "START WITH");
3836 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "AS") ||
3837 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "AS"))
3838 COMPLETE_WITH_CS("smallint", "integer", "bigint");
3839 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "NO") ||
3840 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
3841 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
3842
3843/* CREATE SERVER <name> */
3844 else if (Matches("CREATE", "SERVER", MatchAny))
3845 COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
3846
3847/* CREATE STATISTICS <name> */
3848 else if (Matches("CREATE", "STATISTICS", MatchAny))
3849 COMPLETE_WITH("(", "ON");
3850 else if (Matches("CREATE", "STATISTICS", MatchAny, "("))
3851 COMPLETE_WITH("ndistinct", "dependencies", "mcv");
3852 else if (Matches("CREATE", "STATISTICS", MatchAny, "(*)"))
3853 COMPLETE_WITH("ON");
3854 else if (Matches("CREATE", "STATISTICS", MatchAny, MatchAnyN, "FROM"))
3856
3857/* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3858 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
3859 else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
3860 COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW");
3861 /* Complete "CREATE UNLOGGED" with TABLE or SEQUENCE */
3862 else if (TailMatches("CREATE", "UNLOGGED"))
3863 COMPLETE_WITH("TABLE", "SEQUENCE");
3864 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
3865 else if (TailMatches("PARTITION", "BY"))
3866 COMPLETE_WITH("RANGE (", "LIST (", "HASH (");
3867 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
3868 else if (TailMatches("PARTITION", "OF"))
3870 /* Limited completion support for partition bound specification */
3871 else if (TailMatches("PARTITION", "OF", MatchAny))
3872 COMPLETE_WITH("FOR VALUES", "DEFAULT");
3873 /* Complete CREATE TABLE <name> with '(', AS, OF or PARTITION OF */
3874 else if (TailMatches("CREATE", "TABLE", MatchAny) ||
3875 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny))
3876 COMPLETE_WITH("(", "AS", "OF", "PARTITION OF");
3877 /* Complete CREATE TABLE <name> OF with list of composite types */
3878 else if (TailMatches("CREATE", "TABLE", MatchAny, "OF") ||
3879 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "OF"))
3881 /* Complete CREATE TABLE <name> [ (...) ] AS with list of keywords */
3882 else if (TailMatches("CREATE", "TABLE", MatchAny, "AS") ||
3883 TailMatches("CREATE", "TABLE", MatchAny, "(*)", "AS") ||
3884 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "AS") ||
3885 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "AS"))
3886 COMPLETE_WITH("EXECUTE", "SELECT", "TABLE", "VALUES", "WITH");
3887 /* Complete CREATE TABLE name (...) with supported options */
3888 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)"))
3889 COMPLETE_WITH("AS", "INHERITS (", "PARTITION BY", "USING", "TABLESPACE", "WITH (");
3890 else if (TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)"))
3891 COMPLETE_WITH("AS", "INHERITS (", "USING", "TABLESPACE", "WITH (");
3892 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)"))
3893 COMPLETE_WITH("AS", "INHERITS (", "ON COMMIT", "PARTITION BY", "USING",
3894 "TABLESPACE", "WITH (");
3895 /* Complete CREATE TABLE (...) USING with table access methods */
3896 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "USING") ||
3897 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "USING"))
3899 /* Complete CREATE TABLE (...) WITH with storage parameters */
3900 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "WITH", "(") ||
3901 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "WITH", "("))
3903 /* Complete CREATE TABLE ON COMMIT with actions */
3904 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)", "ON", "COMMIT"))
3905 COMPLETE_WITH("DELETE ROWS", "DROP", "PRESERVE ROWS");
3906
3907/* CREATE TABLESPACE */
3908 else if (Matches("CREATE", "TABLESPACE", MatchAny))
3909 COMPLETE_WITH("OWNER", "LOCATION");
3910 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
3911 else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
3912 COMPLETE_WITH("LOCATION");
3913
3914/* CREATE TEXT SEARCH --- is allowed inside CREATE SCHEMA, so use TailMatches */
3915 else if (TailMatches("CREATE", "TEXT", "SEARCH"))
3916 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3917 else if (TailMatches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
3918 COMPLETE_WITH("(");
3919
3920/* CREATE TRANSFORM */
3921 else if (Matches("CREATE", "TRANSFORM") ||
3922 Matches("CREATE", "OR", "REPLACE", "TRANSFORM"))
3923 COMPLETE_WITH("FOR");
3924 else if (Matches("CREATE", "TRANSFORM", "FOR") ||
3925 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR"))
3927 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny) ||
3928 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny))
3929 COMPLETE_WITH("LANGUAGE");
3930 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE") ||
3931 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3932 {
3935 }
3936
3937/* CREATE SUBSCRIPTION */
3938 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny))
3939 COMPLETE_WITH("CONNECTION", "SERVER");
3940 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER"))
3942 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER", MatchAny))
3943 COMPLETE_WITH("PUBLICATION");
3944 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
3945 COMPLETE_WITH("PUBLICATION");
3946 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER",
3947 MatchAny, "PUBLICATION"))
3948 {
3949 /* complete with nothing here as this refers to remote publications */
3950 }
3951 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
3952 MatchAny, "PUBLICATION"))
3953 {
3954 /* complete with nothing here as this refers to remote publications */
3955 }
3956 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "PUBLICATION", MatchAny))
3957 COMPLETE_WITH("WITH (");
3958 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
3959 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "WITH", "("))
3960 COMPLETE_WITH("binary", "connect", "copy_data", "create_slot",
3961 "disable_on_error", "enabled", "failover",
3962 "max_retention_duration", "origin",
3963 "password_required", "retain_dead_tuples",
3964 "run_as_owner", "slot_name", "streaming",
3965 "synchronous_commit", "two_phase");
3966
3967/* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
3968
3969 /*
3970 * Complete CREATE [ OR REPLACE ] TRIGGER <name> with BEFORE|AFTER|INSTEAD
3971 * OF.
3972 */
3973 else if (TailMatches("CREATE", "TRIGGER", MatchAny) ||
3974 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny))
3975 COMPLETE_WITH("BEFORE", "AFTER", "INSTEAD OF");
3976
3977 /*
3978 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER with an
3979 * event.
3980 */
3981 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER") ||
3982 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
3983 COMPLETE_WITH("INSERT", "DELETE", "UPDATE", "TRUNCATE");
3984 /* Complete CREATE [ OR REPLACE ] TRIGGER <name> INSTEAD OF with an event */
3985 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF") ||
3986 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
3987 COMPLETE_WITH("INSERT", "DELETE", "UPDATE");
3988
3989 /*
3990 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER sth with
3991 * OR|ON.
3992 */
3993 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3994 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3995 TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny) ||
3996 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
3997 COMPLETE_WITH("ON", "OR");
3998
3999 /*
4000 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER event ON
4001 * with a list of tables. EXECUTE FUNCTION is the recommended grammar
4002 * instead of EXECUTE PROCEDURE in version 11 and upwards.
4003 */
4004 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON") ||
4005 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
4007
4008 /*
4009 * Complete CREATE [ OR REPLACE ] TRIGGER ... INSTEAD OF event ON with a
4010 * list of views.
4011 */
4012 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON") ||
4013 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
4015 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4016 "ON", MatchAny) ||
4017 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4018 "ON", MatchAny))
4019 {
4020 if (pset.sversion >= 110000)
4021 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
4022 "REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
4023 else
4024 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
4025 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4026 }
4027 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4028 "DEFERRABLE") ||
4029 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4030 "DEFERRABLE") ||
4031 Matches("CREATE", "TRIGGER", MatchAnyN,
4032 "INITIALLY", "IMMEDIATE|DEFERRED") ||
4033 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4034 "INITIALLY", "IMMEDIATE|DEFERRED"))
4035 {
4036 if (pset.sversion >= 110000)
4037 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
4038 else
4039 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4040 }
4041 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4042 "REFERENCING") ||
4043 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4044 "REFERENCING"))
4045 COMPLETE_WITH("OLD TABLE", "NEW TABLE");
4046 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4047 "OLD|NEW", "TABLE") ||
4048 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4049 "OLD|NEW", "TABLE"))
4050 COMPLETE_WITH("AS");
4051 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4052 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
4053 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4054 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
4055 Matches("CREATE", "TRIGGER", MatchAnyN,
4056 "REFERENCING", "OLD", "TABLE", MatchAny) ||
4057 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4058 "REFERENCING", "OLD", "TABLE", MatchAny))
4059 {
4060 if (pset.sversion >= 110000)
4061 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
4062 else
4063 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4064 }
4065 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4066 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
4067 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4068 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
4069 Matches("CREATE", "TRIGGER", MatchAnyN,
4070 "REFERENCING", "NEW", "TABLE", MatchAny) ||
4071 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4072 "REFERENCING", "NEW", "TABLE", MatchAny))
4073 {
4074 if (pset.sversion >= 110000)
4075 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
4076 else
4077 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4078 }
4079 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4080 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4081 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4082 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4083 Matches("CREATE", "TRIGGER", MatchAnyN,
4084 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4085 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4086 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4087 Matches("CREATE", "TRIGGER", MatchAnyN,
4088 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4089 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4090 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4091 Matches("CREATE", "TRIGGER", MatchAnyN,
4092 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4093 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4094 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny))
4095 {
4096 if (pset.sversion >= 110000)
4097 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE FUNCTION");
4098 else
4099 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE PROCEDURE");
4100 }
4101 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4102 "FOR") ||
4103 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4104 "FOR"))
4105 COMPLETE_WITH("EACH", "ROW", "STATEMENT");
4106 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4107 "FOR", "EACH") ||
4108 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4109 "FOR", "EACH"))
4110 COMPLETE_WITH("ROW", "STATEMENT");
4111 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4112 "FOR", "EACH", "ROW|STATEMENT") ||
4113 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4114 "FOR", "EACH", "ROW|STATEMENT") ||
4115 Matches("CREATE", "TRIGGER", MatchAnyN,
4116 "FOR", "ROW|STATEMENT") ||
4117 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4118 "FOR", "ROW|STATEMENT"))
4119 {
4120 if (pset.sversion >= 110000)
4121 COMPLETE_WITH("WHEN (", "EXECUTE FUNCTION");
4122 else
4123 COMPLETE_WITH("WHEN (", "EXECUTE PROCEDURE");
4124 }
4125 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4126 "WHEN", "(*)") ||
4127 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4128 "WHEN", "(*)"))
4129 {
4130 if (pset.sversion >= 110000)
4131 COMPLETE_WITH("EXECUTE FUNCTION");
4132 else
4133 COMPLETE_WITH("EXECUTE PROCEDURE");
4134 }
4135
4136 /*
4137 * Complete CREATE [ OR REPLACE ] TRIGGER ... EXECUTE with
4138 * PROCEDURE|FUNCTION.
4139 */
4140 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4141 "EXECUTE") ||
4142 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4143 "EXECUTE"))
4144 {
4145 if (pset.sversion >= 110000)
4146 COMPLETE_WITH("FUNCTION");
4147 else
4148 COMPLETE_WITH("PROCEDURE");
4149 }
4150 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4151 "EXECUTE", "FUNCTION|PROCEDURE") ||
4152 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4153 "EXECUTE", "FUNCTION|PROCEDURE"))
4155
4156/* CREATE ROLE,USER,GROUP <name> */
4157 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny) &&
4158 !TailMatches("USER", "MAPPING"))
4159 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
4160 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
4161 "LOGIN", "NOBYPASSRLS",
4162 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
4163 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
4164 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
4165 "VALID UNTIL", "WITH");
4166
4167/* CREATE ROLE,USER,GROUP <name> WITH */
4168 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
4169 /* Similar to the above, but don't complete "WITH" again. */
4170 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
4171 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
4172 "LOGIN", "NOBYPASSRLS",
4173 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
4174 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
4175 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
4176 "VALID UNTIL");
4177
4178 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
4179 else if (Matches("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
4180 COMPLETE_WITH("GROUP", "ROLE");
4181
4182/* CREATE TYPE */
4183 else if (Matches("CREATE", "TYPE", MatchAny))
4184 COMPLETE_WITH("(", "AS");
4185 else if (Matches("CREATE", "TYPE", MatchAny, "AS"))
4186 COMPLETE_WITH("ENUM", "RANGE", "(");
4187 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "("))
4188 {
4189 if (TailMatches("(|*,", MatchAny))
4191 else if (TailMatches("(|*,", MatchAny, MatchAnyExcept("*)")))
4192 COMPLETE_WITH("COLLATE", ",", ")");
4193 }
4194 else if (Matches("CREATE", "TYPE", MatchAny, "AS", "ENUM|RANGE"))
4195 COMPLETE_WITH("(");
4196 else if (HeadMatches("CREATE", "TYPE", MatchAny, "("))
4197 {
4198 if (TailMatches("(|*,"))
4199 COMPLETE_WITH("INPUT", "OUTPUT", "RECEIVE", "SEND",
4200 "TYPMOD_IN", "TYPMOD_OUT", "ANALYZE", "SUBSCRIPT",
4201 "INTERNALLENGTH", "PASSEDBYVALUE", "ALIGNMENT",
4202 "STORAGE", "LIKE", "CATEGORY", "PREFERRED",
4203 "DEFAULT", "ELEMENT", "DELIMITER",
4204 "COLLATABLE");
4205 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
4206 COMPLETE_WITH("=");
4207 else if (TailMatches("=", MatchAnyExcept("*)")))
4208 COMPLETE_WITH(",", ")");
4209 }
4210 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "RANGE", "("))
4211 {
4212 if (TailMatches("(|*,"))
4213 COMPLETE_WITH("SUBTYPE", "SUBTYPE_OPCLASS", "COLLATION",
4214 "CANONICAL", "SUBTYPE_DIFF",
4215 "MULTIRANGE_TYPE_NAME");
4216 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
4217 COMPLETE_WITH("=");
4218 else if (TailMatches("=", MatchAnyExcept("*)")))
4219 COMPLETE_WITH(",", ")");
4220 }
4221
4222/* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
4223 /* Complete CREATE [ OR REPLACE ] VIEW <name> with AS or WITH */
4224 else if (TailMatches("CREATE", "VIEW", MatchAny) ||
4225 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny))
4226 COMPLETE_WITH("AS", "WITH");
4227 /* Complete "CREATE [ OR REPLACE ] VIEW <sth> AS with "SELECT" */
4228 else if (TailMatches("CREATE", "VIEW", MatchAny, "AS") ||
4229 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "AS"))
4230 COMPLETE_WITH("SELECT");
4231 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( yyy [= zzz] ) */
4232 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH") ||
4233 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH"))
4234 COMPLETE_WITH("(");
4235 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(") ||
4236 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "("))
4238 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option") ||
4239 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option"))
4240 COMPLETE_WITH("=");
4241 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option", "=") ||
4242 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option", "="))
4243 COMPLETE_WITH("local", "cascaded");
4244 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS */
4245 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)") ||
4246 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)"))
4247 COMPLETE_WITH("AS");
4248 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS SELECT */
4249 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)", "AS") ||
4250 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)", "AS"))
4251 COMPLETE_WITH("SELECT");
4252
4253/* CREATE MATERIALIZED VIEW */
4254 else if (Matches("CREATE", "MATERIALIZED"))
4255 COMPLETE_WITH("VIEW");
4256 /* Complete CREATE MATERIALIZED VIEW <name> with AS or USING */
4257 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
4258 COMPLETE_WITH("AS", "USING");
4259
4260 /*
4261 * Complete CREATE MATERIALIZED VIEW <name> USING with list of access
4262 * methods
4263 */
4264 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING"))
4266 /* Complete CREATE MATERIALIZED VIEW <name> USING <access method> with AS */
4267 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny))
4268 COMPLETE_WITH("AS");
4269
4270 /*
4271 * Complete CREATE MATERIALIZED VIEW <name> [USING <access method> ] AS
4272 * with "SELECT"
4273 */
4274 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS") ||
4275 Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS"))
4276 COMPLETE_WITH("SELECT");
4277
4278/* CREATE EVENT TRIGGER */
4279 else if (Matches("CREATE", "EVENT"))
4280 COMPLETE_WITH("TRIGGER");
4281 /* Complete CREATE EVENT TRIGGER <name> with ON */
4282 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny))
4283 COMPLETE_WITH("ON");
4284 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
4285 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
4286 COMPLETE_WITH("ddl_command_start", "ddl_command_end", "login",
4287 "sql_drop", "table_rewrite");
4288
4289 /*
4290 * Complete CREATE EVENT TRIGGER <name> ON <event_type>. EXECUTE FUNCTION
4291 * is the recommended grammar instead of EXECUTE PROCEDURE in version 11
4292 * and upwards.
4293 */
4294 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON", MatchAny))
4295 {
4296 if (pset.sversion >= 110000)
4297 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE FUNCTION");
4298 else
4299 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE PROCEDURE");
4300 }
4301 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "WHEN|AND", MatchAny, "IN", "(*)"))
4302 {
4303 if (pset.sversion >= 110000)
4304 COMPLETE_WITH("EXECUTE FUNCTION");
4305 else
4306 COMPLETE_WITH("EXECUTE PROCEDURE");
4307 }
4308 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "EXECUTE", "FUNCTION|PROCEDURE"))
4310
4311/* DEALLOCATE */
4312 else if (Matches("DEALLOCATE"))
4314 "ALL");
4315
4316/* DECLARE */
4317
4318 /*
4319 * Complete DECLARE <name> with one of BINARY, ASENSITIVE, INSENSITIVE,
4320 * SCROLL, NO SCROLL, and CURSOR.
4321 */
4322 else if (Matches("DECLARE", MatchAny))
4323 COMPLETE_WITH("BINARY", "ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL",
4324 "CURSOR");
4325
4326 /*
4327 * Complete DECLARE ... <option> with other options. The PostgreSQL parser
4328 * allows DECLARE options to be specified in any order. But the
4329 * tab-completion follows the ordering of them that the SQL standard
4330 * provides, like the syntax of DECLARE command in the documentation
4331 * indicates.
4332 */
4333 else if (Matches("DECLARE", MatchAnyN, "BINARY"))
4334 COMPLETE_WITH("ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR");
4335 else if (Matches("DECLARE", MatchAnyN, "ASENSITIVE|INSENSITIVE"))
4336 COMPLETE_WITH("SCROLL", "NO SCROLL", "CURSOR");
4337 else if (Matches("DECLARE", MatchAnyN, "SCROLL"))
4338 COMPLETE_WITH("CURSOR");
4339 /* Complete DECLARE ... [options] NO with SCROLL */
4340 else if (Matches("DECLARE", MatchAnyN, "NO"))
4341 COMPLETE_WITH("SCROLL");
4342
4343 /*
4344 * Complete DECLARE ... CURSOR with one of WITH HOLD, WITHOUT HOLD, and
4345 * FOR
4346 */
4347 else if (Matches("DECLARE", MatchAnyN, "CURSOR"))
4348 COMPLETE_WITH("WITH HOLD", "WITHOUT HOLD", "FOR");
4349 /* Complete DECLARE ... CURSOR WITH|WITHOUT with HOLD */
4350 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT"))
4351 COMPLETE_WITH("HOLD");
4352 /* Complete DECLARE ... CURSOR WITH|WITHOUT HOLD with FOR */
4353 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT", "HOLD"))
4354 COMPLETE_WITH("FOR");
4355
4356/* DELETE --- can be inside EXPLAIN, RULE, etc */
4357 /* Complete DELETE with "FROM" */
4358 else if (Matches("DELETE"))
4359 COMPLETE_WITH("FROM");
4360 /* Complete DELETE FROM with a list of tables */
4361 else if (TailMatches("DELETE", "FROM"))
4363 /* Complete DELETE FROM <table> */
4364 else if (TailMatches("DELETE", "FROM", MatchAny))
4365 COMPLETE_WITH("USING", "WHERE");
4366 /* Complete DELETE FROM <table> USING with relations supporting SELECT */
4367 else if (TailMatches("DELETE", "FROM", MatchAny, "USING"))
4369
4370/* DISCARD */
4371 else if (Matches("DISCARD"))
4372 COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP");
4373
4374/* DO */
4375 else if (Matches("DO"))
4376 COMPLETE_WITH("LANGUAGE");
4377
4378/* DROP */
4379 /* Complete DROP object with CASCADE / RESTRICT */
4380 else if (Matches("DROP",
4381 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
4382 MatchAny) ||
4383 Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
4384 Matches("DROP", "EVENT", "TRIGGER", MatchAny) ||
4385 Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4386 Matches("DROP", "FOREIGN", "TABLE", MatchAny) ||
4387 Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
4388 COMPLETE_WITH("CASCADE", "RESTRICT");
4389 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
4390 ends_with(prev_wd, ')'))
4391 COMPLETE_WITH("CASCADE", "RESTRICT");
4392
4393 /* help completing some of the variants */
4394 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
4395 COMPLETE_WITH("(");
4396 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
4398 else if (Matches("DROP", "FOREIGN"))
4399 COMPLETE_WITH("DATA WRAPPER", "TABLE");
4400 else if (Matches("DROP", "DATABASE", MatchAny))
4401 COMPLETE_WITH("WITH (");
4402 else if (HeadMatches("DROP", "DATABASE") && (ends_with(prev_wd, '(')))
4403 COMPLETE_WITH("FORCE");
4404
4405 /* DROP INDEX */
4406 else if (Matches("DROP", "INDEX"))
4408 "CONCURRENTLY");
4409 else if (Matches("DROP", "INDEX", "CONCURRENTLY"))
4411 else if (Matches("DROP", "INDEX", MatchAny))
4412 COMPLETE_WITH("CASCADE", "RESTRICT");
4413 else if (Matches("DROP", "INDEX", "CONCURRENTLY", MatchAny))
4414 COMPLETE_WITH("CASCADE", "RESTRICT");
4415
4416 /* DROP MATERIALIZED VIEW */
4417 else if (Matches("DROP", "MATERIALIZED"))
4418 COMPLETE_WITH("VIEW");
4419 else if (Matches("DROP", "MATERIALIZED", "VIEW"))
4421 else if (Matches("DROP", "MATERIALIZED", "VIEW", MatchAny))
4422 COMPLETE_WITH("CASCADE", "RESTRICT");
4423
4424 /* DROP OWNED BY */
4425 else if (Matches("DROP", "OWNED"))
4426 COMPLETE_WITH("BY");
4427 else if (Matches("DROP", "OWNED", "BY"))
4429 else if (Matches("DROP", "OWNED", "BY", MatchAny))
4430 COMPLETE_WITH("CASCADE", "RESTRICT");
4431
4432 /* DROP TEXT SEARCH */
4433 else if (Matches("DROP", "TEXT", "SEARCH"))
4434 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
4435
4436 /* DROP TRIGGER */
4437 else if (Matches("DROP", "TRIGGER", MatchAny))
4438 COMPLETE_WITH("ON");
4439 else if (Matches("DROP", "TRIGGER", MatchAny, "ON"))
4440 {
4443 }
4444 else if (Matches("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
4445 COMPLETE_WITH("CASCADE", "RESTRICT");
4446
4447 /* DROP ACCESS METHOD */
4448 else if (Matches("DROP", "ACCESS"))
4449 COMPLETE_WITH("METHOD");
4450 else if (Matches("DROP", "ACCESS", "METHOD"))
4452
4453 /* DROP EVENT TRIGGER */
4454 else if (Matches("DROP", "EVENT"))
4455 COMPLETE_WITH("TRIGGER");
4456 else if (Matches("DROP", "EVENT", "TRIGGER"))
4458
4459 /* DROP POLICY <name> */
4460 else if (Matches("DROP", "POLICY"))
4462 /* DROP POLICY <name> ON */
4463 else if (Matches("DROP", "POLICY", MatchAny))
4464 COMPLETE_WITH("ON");
4465 /* DROP POLICY <name> ON <table> */
4466 else if (Matches("DROP", "POLICY", MatchAny, "ON"))
4467 {
4470 }
4471 else if (Matches("DROP", "POLICY", MatchAny, "ON", MatchAny))
4472 COMPLETE_WITH("CASCADE", "RESTRICT");
4473
4474 /* DROP PROPERTY GRAPH */
4475 else if (Matches("DROP", "PROPERTY"))
4476 COMPLETE_WITH("GRAPH");
4477 else if (Matches("DROP", "PROPERTY", "GRAPH"))
4479
4480 /* DROP RULE */
4481 else if (Matches("DROP", "RULE", MatchAny))
4482 COMPLETE_WITH("ON");
4483 else if (Matches("DROP", "RULE", MatchAny, "ON"))
4484 {
4487 }
4488 else if (Matches("DROP", "RULE", MatchAny, "ON", MatchAny))
4489 COMPLETE_WITH("CASCADE", "RESTRICT");
4490
4491 /* DROP TRANSFORM */
4492 else if (Matches("DROP", "TRANSFORM"))
4493 COMPLETE_WITH("FOR");
4494 else if (Matches("DROP", "TRANSFORM", "FOR"))
4496 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny))
4497 COMPLETE_WITH("LANGUAGE");
4498 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
4499 {
4502 }
4503 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE", MatchAny))
4504 COMPLETE_WITH("CASCADE", "RESTRICT");
4505
4506/* EXECUTE */
4507 else if (Matches("EXECUTE"))
4509
4510/*
4511 * EXPLAIN [ ( option [, ...] ) ] statement
4512 * EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
4513 */
4514 else if (Matches("EXPLAIN"))
4515 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4516 "MERGE INTO", "EXECUTE", "ANALYZE", "VERBOSE");
4517 else if (HeadMatches("EXPLAIN", "(*") &&
4518 !HeadMatches("EXPLAIN", "(*)"))
4519 {
4520 /*
4521 * This fires if we're in an unfinished parenthesized option list.
4522 * get_previous_words treats a completed parenthesized option list as
4523 * one word, so the above test is correct.
4524 */
4525 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
4526 COMPLETE_WITH("ANALYZE", "VERBOSE", "COSTS", "SETTINGS", "GENERIC_PLAN",
4527 "BUFFERS", "SERIALIZE", "WAL", "TIMING", "SUMMARY",
4528 "MEMORY", "FORMAT");
4529 else if (TailMatches("ANALYZE|VERBOSE|COSTS|SETTINGS|GENERIC_PLAN|BUFFERS|WAL|TIMING|SUMMARY|MEMORY"))
4530 COMPLETE_WITH("ON", "OFF");
4531 else if (TailMatches("SERIALIZE"))
4532 COMPLETE_WITH("TEXT", "NONE", "BINARY");
4533 else if (TailMatches("FORMAT"))
4534 COMPLETE_WITH("TEXT", "XML", "JSON", "YAML");
4535 }
4536 else if (Matches("EXPLAIN", "ANALYZE"))
4537 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4538 "MERGE INTO", "EXECUTE", "VERBOSE");
4539 else if (Matches("EXPLAIN", "(*)") ||
4540 Matches("EXPLAIN", "VERBOSE") ||
4541 Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
4542 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4543 "MERGE INTO", "EXECUTE");
4544
4545/* FETCH && MOVE */
4546
4547 /*
4548 * Complete FETCH with one of ABSOLUTE, BACKWARD, FORWARD, RELATIVE, ALL,
4549 * NEXT, PRIOR, FIRST, LAST, FROM, IN, and a list of cursors
4550 */
4551 else if (Matches("FETCH|MOVE"))
4553 "ABSOLUTE",
4554 "BACKWARD",
4555 "FORWARD",
4556 "RELATIVE",
4557 "ALL",
4558 "NEXT",
4559 "PRIOR",
4560 "FIRST",
4561 "LAST",
4562 "FROM",
4563 "IN");
4564
4565 /*
4566 * Complete FETCH BACKWARD or FORWARD with one of ALL, FROM, IN, and a
4567 * list of cursors
4568 */
4569 else if (Matches("FETCH|MOVE", "BACKWARD|FORWARD"))
4571 "ALL",
4572 "FROM",
4573 "IN");
4574
4575 /*
4576 * Complete FETCH <direction> with "FROM" or "IN". These are equivalent,
4577 * but we may as well tab-complete both: perhaps some users prefer one
4578 * variant or the other.
4579 */
4580 else if (Matches("FETCH|MOVE", "ABSOLUTE|BACKWARD|FORWARD|RELATIVE",
4581 MatchAnyExcept("FROM|IN")) ||
4582 Matches("FETCH|MOVE", "ALL|NEXT|PRIOR|FIRST|LAST"))
4584 "FROM",
4585 "IN");
4586 /* Complete FETCH <direction> "FROM" or "IN" with a list of cursors */
4587 else if (Matches("FETCH|MOVE", MatchAnyN, "FROM|IN"))
4589
4590/* FOREIGN DATA WRAPPER */
4591 /* applies in ALTER/DROP FDW and in CREATE SERVER */
4592 else if (TailMatches("FOREIGN", "DATA", "WRAPPER") &&
4593 !TailMatches("CREATE", MatchAny, MatchAny, MatchAny))
4595 /* applies in CREATE SERVER */
4596 else if (Matches("CREATE", "SERVER", MatchAnyN, "FOREIGN", "DATA", "WRAPPER", MatchAny))
4597 COMPLETE_WITH("OPTIONS");
4598
4599/* FOREIGN TABLE */
4600 else if (TailMatches("FOREIGN", "TABLE") &&
4601 !TailMatches("CREATE", MatchAny, MatchAny))
4603
4604/* FOREIGN SERVER */
4605 else if (TailMatches("FOREIGN", "SERVER"))
4607
4608/*
4609 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
4610 * ALTER DEFAULT PRIVILEGES, so use TailMatches
4611 */
4612 /* Complete GRANT/REVOKE with a list of roles and privileges */
4613 else if (TailMatches("GRANT|REVOKE") ||
4614 TailMatches("REVOKE", "ADMIN|GRANT|INHERIT|SET", "OPTION", "FOR"))
4615 {
4616 /*
4617 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
4618 * privileges (can't grant roles)
4619 */
4620 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4621 {
4622 if (TailMatches("GRANT") ||
4623 TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4624 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4625 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4626 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL");
4627 else if (TailMatches("REVOKE"))
4628 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4629 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4630 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL",
4631 "GRANT OPTION FOR");
4632 }
4633 else if (TailMatches("GRANT"))
4636 else if (TailMatches("REVOKE"))
4639 "GRANT OPTION FOR",
4640 "ADMIN OPTION FOR",
4641 "INHERIT OPTION FOR",
4642 "SET OPTION FOR");
4643 else if (TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4645 else if (TailMatches("REVOKE", "ADMIN|INHERIT|SET", "OPTION", "FOR"))
4647 }
4648
4649 else if (TailMatches("GRANT|REVOKE", "ALTER") ||
4650 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER"))
4651 COMPLETE_WITH("SYSTEM");
4652
4653 else if (TailMatches("REVOKE", "SET"))
4654 COMPLETE_WITH("ON PARAMETER", "OPTION FOR");
4655 else if (TailMatches("GRANT", "SET") ||
4656 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "SET") ||
4657 TailMatches("GRANT|REVOKE", "ALTER", "SYSTEM") ||
4658 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER", "SYSTEM"))
4659 COMPLETE_WITH("ON PARAMETER");
4660
4661 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "PARAMETER") ||
4662 TailMatches("GRANT|REVOKE", MatchAny, MatchAny, "ON", "PARAMETER") ||
4663 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER") ||
4664 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER"))
4666
4667 else if (TailMatches("GRANT", MatchAny, "ON", "PARAMETER", MatchAny) ||
4668 TailMatches("GRANT", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4669 COMPLETE_WITH("TO");
4670
4671 else if (TailMatches("REVOKE", MatchAny, "ON", "PARAMETER", MatchAny) ||
4672 TailMatches("REVOKE", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny) ||
4673 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER", MatchAny) ||
4674 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4675 COMPLETE_WITH("FROM");
4676
4677 /*
4678 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
4679 * TO/FROM
4680 */
4681 else if (TailMatches("GRANT|REVOKE", MatchAny) ||
4682 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny))
4683 {
4684 if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|MAINTAIN|ALL"))
4685 COMPLETE_WITH("ON");
4686 else if (TailMatches("GRANT", MatchAny))
4687 COMPLETE_WITH("TO");
4688 else
4689 COMPLETE_WITH("FROM");
4690 }
4691
4692 /*
4693 * Complete GRANT/REVOKE <sth> ON with a list of appropriate relations.
4694 *
4695 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
4696 * here will only work if the privilege list contains exactly one
4697 * privilege.
4698 */
4699 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON") ||
4700 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON"))
4701 {
4702 /*
4703 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
4704 * objects supported.
4705 */
4706 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4707 COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS", "LARGE OBJECTS");
4708 else
4710 "ALL FUNCTIONS IN SCHEMA",
4711 "ALL PROCEDURES IN SCHEMA",
4712 "ALL ROUTINES IN SCHEMA",
4713 "ALL SEQUENCES IN SCHEMA",
4714 "ALL TABLES IN SCHEMA",
4715 "DATABASE",
4716 "DOMAIN",
4717 "FOREIGN DATA WRAPPER",
4718 "FOREIGN SERVER",
4719 "FUNCTION",
4720 "LANGUAGE",
4721 "LARGE OBJECT",
4722 "PARAMETER",
4723 "PROCEDURE",
4724 "PROPERTY GRAPH",
4725 "ROUTINE",
4726 "SCHEMA",
4727 "SEQUENCE",
4728 "TABLE",
4729 "TABLESPACE",
4730 "TYPE");
4731 }
4732 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
4733 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
4734 COMPLETE_WITH("FUNCTIONS IN SCHEMA",
4735 "PROCEDURES IN SCHEMA",
4736 "ROUTINES IN SCHEMA",
4737 "SEQUENCES IN SCHEMA",
4738 "TABLES IN SCHEMA");
4739
4740 /*
4741 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
4742 * appropriate objects or keywords.
4743 *
4744 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
4745 */
4746 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny) ||
4747 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny))
4748 {
4749 if (TailMatches("DATABASE"))
4751 else if (TailMatches("DOMAIN"))
4753 else if (TailMatches("FUNCTION"))
4755 else if (TailMatches("FOREIGN"))
4756 COMPLETE_WITH("DATA WRAPPER", "SERVER");
4757 else if (TailMatches("LANGUAGE"))
4759 else if (TailMatches("LARGE"))
4760 {
4761 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4762 COMPLETE_WITH("OBJECTS");
4763 else
4764 COMPLETE_WITH("OBJECT");
4765 }
4766 else if (TailMatches("PROCEDURE"))
4768 else if (TailMatches("ROUTINE"))
4770 else if (TailMatches("SCHEMA"))
4772 else if (TailMatches("SEQUENCE"))
4774 else if (TailMatches("TABLE"))
4776 else if (TailMatches("TABLESPACE"))
4778 else if (TailMatches("TYPE"))
4780 else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
4781 COMPLETE_WITH("TO");
4782 else
4783 COMPLETE_WITH("FROM");
4784 }
4785
4786 /*
4787 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
4788 * CURRENT_ROLE, CURRENT_USER, or SESSION_USER.
4789 */
4790 else if (Matches("GRANT", MatchAnyN, "TO") ||
4791 Matches("REVOKE", MatchAnyN, "FROM"))
4794
4795 /*
4796 * Offer grant options after that.
4797 */
4798 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny))
4799 COMPLETE_WITH("WITH ADMIN",
4800 "WITH INHERIT",
4801 "WITH SET",
4802 "WITH GRANT OPTION",
4803 "GRANTED BY");
4804 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH"))
4805 COMPLETE_WITH("ADMIN",
4806 "INHERIT",
4807 "SET",
4808 "GRANT OPTION");
4809 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", "ADMIN|INHERIT|SET"))
4810 COMPLETE_WITH("OPTION", "TRUE", "FALSE");
4811 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION"))
4812 COMPLETE_WITH("GRANTED BY");
4813 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY"))
4816 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
4817 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO|FROM"))
4820 /* Offer WITH GRANT OPTION after that */
4821 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO", MatchAny))
4822 COMPLETE_WITH("WITH GRANT OPTION");
4823 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
4824 else if (Matches("GRANT|REVOKE", MatchAnyN, "ON", MatchAny, MatchAny) &&
4825 !TailMatches("FOREIGN", "SERVER") && !TailMatches("LARGE", "OBJECT"))
4826 {
4827 if (Matches("GRANT", MatchAnyN, "ON", MatchAny, MatchAny))
4828 COMPLETE_WITH("TO");
4829 else
4830 COMPLETE_WITH("FROM");
4831 }
4832
4833 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
4834 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
4835 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
4836 {
4838 COMPLETE_WITH("TO");
4839 else
4840 COMPLETE_WITH("FROM");
4841 }
4842
4843 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
4844 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4845 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
4846 {
4848 COMPLETE_WITH("TO");
4849 else
4850 COMPLETE_WITH("FROM");
4851 }
4852
4853 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
4854 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
4855 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
4856 {
4858 COMPLETE_WITH("TO");
4859 else
4860 COMPLETE_WITH("FROM");
4861 }
4862
4863 /* Complete "GRANT/REVOKE * ON LARGE OBJECT *" with TO/FROM */
4864 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "LARGE", "OBJECT", MatchAny) ||
4865 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "LARGE", "OBJECT", MatchAny))
4866 {
4868 COMPLETE_WITH("TO");
4869 else
4870 COMPLETE_WITH("FROM");
4871 }
4872
4873 /* Complete "GRANT/REVOKE * ON LARGE OBJECTS" with TO/FROM */
4874 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "LARGE", "OBJECTS") ||
4875 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "LARGE", "OBJECTS"))
4876 {
4878 COMPLETE_WITH("TO");
4879 else
4880 COMPLETE_WITH("FROM");
4881 }
4882
4883/* GRAPH_TABLE */
4884 else if (TailMatches("GRAPH_TABLE"))
4885 COMPLETE_WITH("(");
4886 else if (TailMatches("GRAPH_TABLE", "("))
4888 else if (TailMatches("GRAPH_TABLE", "(", MatchAny))
4889 COMPLETE_WITH("MATCH");
4890
4891/* GROUP BY */
4892 else if (TailMatches("FROM", MatchAny, "GROUP"))
4893 COMPLETE_WITH("BY");
4894
4895/* IMPORT FOREIGN SCHEMA */
4896 else if (Matches("IMPORT"))
4897 COMPLETE_WITH("FOREIGN SCHEMA");
4898 else if (Matches("IMPORT", "FOREIGN"))
4899 COMPLETE_WITH("SCHEMA");
4900 else if (Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny))
4901 COMPLETE_WITH("EXCEPT (", "FROM SERVER", "LIMIT TO (");
4902 else if (TailMatches("LIMIT", "TO", "(*)") ||
4903 Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny, "EXCEPT", "(*)"))
4904 COMPLETE_WITH("FROM SERVER");
4905 else if (TailMatches("FROM", "SERVER", MatchAny))
4906 COMPLETE_WITH("INTO");
4907 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO"))
4909 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO", MatchAny))
4910 COMPLETE_WITH("OPTIONS (");
4911
4912/* INSERT --- can be inside EXPLAIN, RULE, etc */
4913 /* Complete NOT MATCHED THEN INSERT */
4914 else if (TailMatches("NOT", "MATCHED", "THEN", "INSERT"))
4915 COMPLETE_WITH("VALUES", "(");
4916 /* Complete INSERT with "INTO" */
4917 else if (TailMatches("INSERT"))
4918 COMPLETE_WITH("INTO");
4919 /* Complete INSERT INTO with table names */
4920 else if (TailMatches("INSERT", "INTO"))
4922 /* Complete "INSERT INTO <table> (" with attribute names */
4923 else if (TailMatches("INSERT", "INTO", MatchAny, "("))
4925
4926 /*
4927 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
4928 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
4929 */
4930 else if (TailMatches("INSERT", "INTO", MatchAny))
4931 COMPLETE_WITH("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
4932
4933 /*
4934 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
4935 * "TABLE" or "OVERRIDING"
4936 */
4937 else if (TailMatches("INSERT", "INTO", MatchAny, MatchAny) &&
4938 ends_with(prev_wd, ')'))
4939 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "OVERRIDING");
4940
4941 /* Complete OVERRIDING */
4942 else if (TailMatches("OVERRIDING"))
4943 COMPLETE_WITH("SYSTEM VALUE", "USER VALUE");
4944
4945 /* Complete after OVERRIDING clause */
4946 else if (TailMatches("OVERRIDING", MatchAny, "VALUE"))
4947 COMPLETE_WITH("SELECT", "TABLE", "VALUES");
4948
4949 /* Insert an open parenthesis after "VALUES" */
4950 else if (TailMatches("VALUES") && !TailMatches("DEFAULT", "VALUES"))
4951 COMPLETE_WITH("(");
4952
4953/* LOCK */
4954 /* Complete LOCK [TABLE] [ONLY] with a list of tables */
4955 else if (Matches("LOCK"))
4957 "TABLE", "ONLY");
4958 else if (Matches("LOCK", "TABLE"))
4960 "ONLY");
4961 else if (Matches("LOCK", "TABLE", "ONLY") || Matches("LOCK", "ONLY"))
4963 /* For the following, handle the case of a single table only for now */
4964
4965 /* Complete LOCK [TABLE] [ONLY] <table> with IN or NOWAIT */
4966 else if (Matches("LOCK", MatchAnyExcept("TABLE|ONLY")) ||
4967 Matches("LOCK", "TABLE", MatchAnyExcept("ONLY")) ||
4968 Matches("LOCK", "ONLY", MatchAny) ||
4969 Matches("LOCK", "TABLE", "ONLY", MatchAny))
4970 COMPLETE_WITH("IN", "NOWAIT");
4971
4972 /* Complete LOCK [TABLE] [ONLY] <table> IN with a lock mode */
4973 else if (Matches("LOCK", MatchAnyN, "IN"))
4974 COMPLETE_WITH("ACCESS SHARE MODE",
4975 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
4976 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
4977 "SHARE ROW EXCLUSIVE MODE",
4978 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
4979
4980 /*
4981 * Complete LOCK [TABLE][ONLY] <table> IN ACCESS|ROW with rest of lock
4982 * mode
4983 */
4984 else if (Matches("LOCK", MatchAnyN, "IN", "ACCESS|ROW"))
4985 COMPLETE_WITH("EXCLUSIVE MODE", "SHARE MODE");
4986
4987 /* Complete LOCK [TABLE] [ONLY] <table> IN SHARE with rest of lock mode */
4988 else if (Matches("LOCK", MatchAnyN, "IN", "SHARE"))
4989 COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE",
4990 "UPDATE EXCLUSIVE MODE");
4991
4992 /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with "NOWAIT" */
4993 else if (Matches("LOCK", MatchAnyN, "MODE"))
4994 COMPLETE_WITH("NOWAIT");
4995
4996/* MERGE --- can be inside EXPLAIN */
4997 else if (TailMatches("MERGE"))
4998 COMPLETE_WITH("INTO");
4999 else if (TailMatches("MERGE", "INTO"))
5001
5002 /* Complete MERGE INTO <table> [[AS] <alias>] with USING */
5003 else if (TailMatches("MERGE", "INTO", MatchAny))
5004 COMPLETE_WITH("USING", "AS");
5005 else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
5006 TailMatches("MERGE", "INTO", MatchAny, MatchAnyExcept("USING|AS")))
5007 COMPLETE_WITH("USING");
5008
5009 /*
5010 * Complete MERGE INTO ... USING with a list of relations supporting
5011 * SELECT
5012 */
5013 else if (TailMatches("MERGE", "INTO", MatchAny, "USING") ||
5014 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING") ||
5015 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING"))
5017
5018 /*
5019 * Complete MERGE INTO <table> [[AS] <alias>] USING <relations> [[AS]
5020 * alias] with ON
5021 */
5022 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny) ||
5023 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny) ||
5024 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny))
5025 COMPLETE_WITH("AS", "ON");
5026 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5027 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5028 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5029 TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
5030 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
5031 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")))
5032 COMPLETE_WITH("ON");
5033
5034 /* Complete MERGE INTO ... ON with target table attributes */
5035 else if (TailMatches("INTO", MatchAny, "USING", MatchAny, "ON"))
5037 else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny, "ON"))
5039 else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAny, "ON"))
5041
5042 /*
5043 * Complete ... USING <relation> [[AS] alias] ON join condition
5044 * (consisting of one or three words typically used) with WHEN [NOT]
5045 * MATCHED
5046 */
5047 else if (TailMatches("USING", MatchAny, "ON", MatchAny) ||
5048 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny) ||
5049 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny) ||
5050 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
5051 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
5052 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")))
5053 COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
5054 else if (TailMatches("USING", MatchAny, "ON", MatchAny, "WHEN") ||
5055 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, "WHEN") ||
5056 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, "WHEN") ||
5057 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
5058 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
5059 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN"))
5060 COMPLETE_WITH("MATCHED", "NOT MATCHED");
5061
5062 /*
5063 * Complete ... WHEN MATCHED and WHEN NOT MATCHED BY SOURCE|TARGET with
5064 * THEN/AND
5065 */
5066 else if (TailMatches("WHEN", "MATCHED") ||
5067 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE|TARGET"))
5068 COMPLETE_WITH("THEN", "AND");
5069
5070 /* Complete ... WHEN NOT MATCHED with BY/THEN/AND */
5071 else if (TailMatches("WHEN", "NOT", "MATCHED"))
5072 COMPLETE_WITH("BY", "THEN", "AND");
5073
5074 /* Complete ... WHEN NOT MATCHED BY with SOURCE/TARGET */
5075 else if (TailMatches("WHEN", "NOT", "MATCHED", "BY"))
5076 COMPLETE_WITH("SOURCE", "TARGET");
5077
5078 /*
5079 * Complete ... WHEN MATCHED THEN and WHEN NOT MATCHED BY SOURCE THEN with
5080 * UPDATE SET/DELETE/DO NOTHING
5081 */
5082 else if (TailMatches("WHEN", "MATCHED", "THEN") ||
5083 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE", "THEN"))
5084 COMPLETE_WITH("UPDATE SET", "DELETE", "DO NOTHING");
5085
5086 /*
5087 * Complete ... WHEN NOT MATCHED [BY TARGET] THEN with INSERT/DO NOTHING
5088 */
5089 else if (TailMatches("WHEN", "NOT", "MATCHED", "THEN") ||
5090 TailMatches("WHEN", "NOT", "MATCHED", "BY", "TARGET", "THEN"))
5091 COMPLETE_WITH("INSERT", "DO NOTHING");
5092
5093/* NOTIFY --- can be inside EXPLAIN, RULE, etc */
5094 else if (TailMatches("NOTIFY"))
5096
5097/* OPTIONS */
5098 else if (TailMatches("OPTIONS"))
5099 COMPLETE_WITH("(");
5100
5101/* OWNER TO - complete with available roles */
5102 else if (TailMatches("OWNER", "TO"))
5105
5106/* ORDER BY */
5107 else if (TailMatches("FROM", MatchAny, "ORDER"))
5108 COMPLETE_WITH("BY");
5109 else if (TailMatches("FROM", MatchAny, "ORDER", "BY"))
5111
5112/* PREPARE xx AS */
5113 else if (Matches("PREPARE", MatchAny, "AS"))
5114 COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM",
5115 "MERGE INTO", "VALUES", "WITH", "TABLE");
5116
5117/*
5118 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
5119 * managers, not for manual use in interactive sessions.
5120 */
5121
5122/* REASSIGN OWNED BY xxx TO yyy */
5123 else if (Matches("REASSIGN"))
5124 COMPLETE_WITH("OWNED BY");
5125 else if (Matches("REASSIGN", "OWNED"))
5126 COMPLETE_WITH("BY");
5127 else if (Matches("REASSIGN", "OWNED", "BY"))
5129 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny))
5130 COMPLETE_WITH("TO");
5131 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
5133
5134/* REFRESH MATERIALIZED VIEW */
5135 else if (Matches("REFRESH"))
5136 COMPLETE_WITH("MATERIALIZED VIEW");
5137 else if (Matches("REFRESH", "MATERIALIZED"))
5138 COMPLETE_WITH("VIEW");
5139 else if (Matches("REFRESH", "MATERIALIZED", "VIEW"))
5141 "CONCURRENTLY");
5142 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
5144 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
5145 COMPLETE_WITH("WITH");
5146 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
5147 COMPLETE_WITH("WITH");
5148 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
5149 COMPLETE_WITH("NO DATA", "DATA");
5150 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
5151 COMPLETE_WITH("NO DATA", "DATA");
5152 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
5153 COMPLETE_WITH("DATA");
5154 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
5155 COMPLETE_WITH("DATA");
5156
5157/* REINDEX */
5158 else if (Matches("REINDEX") ||
5159 Matches("REINDEX", "(*)"))
5160 COMPLETE_WITH("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
5161 else if (Matches("REINDEX", "TABLE") ||
5162 Matches("REINDEX", "(*)", "TABLE"))
5164 "CONCURRENTLY");
5165 else if (Matches("REINDEX", "INDEX") ||
5166 Matches("REINDEX", "(*)", "INDEX"))
5168 "CONCURRENTLY");
5169 else if (Matches("REINDEX", "SCHEMA") ||
5170 Matches("REINDEX", "(*)", "SCHEMA"))
5172 "CONCURRENTLY");
5173 else if (Matches("REINDEX", "SYSTEM|DATABASE") ||
5174 Matches("REINDEX", "(*)", "SYSTEM|DATABASE"))
5176 "CONCURRENTLY");
5177 else if (Matches("REINDEX", "TABLE", "CONCURRENTLY") ||
5178 Matches("REINDEX", "(*)", "TABLE", "CONCURRENTLY"))
5180 else if (Matches("REINDEX", "INDEX", "CONCURRENTLY") ||
5181 Matches("REINDEX", "(*)", "INDEX", "CONCURRENTLY"))
5183 else if (Matches("REINDEX", "SCHEMA", "CONCURRENTLY") ||
5184 Matches("REINDEX", "(*)", "SCHEMA", "CONCURRENTLY"))
5186 else if (Matches("REINDEX", "SYSTEM|DATABASE", "CONCURRENTLY") ||
5187 Matches("REINDEX", "(*)", "SYSTEM|DATABASE", "CONCURRENTLY"))
5189 else if (HeadMatches("REINDEX", "(*") &&
5190 !HeadMatches("REINDEX", "(*)"))
5191 {
5192 /*
5193 * This fires if we're in an unfinished parenthesized option list.
5194 * get_previous_words treats a completed parenthesized option list as
5195 * one word, so the above test is correct.
5196 */
5197 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5198 COMPLETE_WITH("CONCURRENTLY", "TABLESPACE", "VERBOSE");
5199 else if (TailMatches("TABLESPACE"))
5201 }
5202
5203/* REPACK */
5204 else if (Matches("REPACK"))
5206 "(", "USING INDEX");
5207 else if (Matches("REPACK", "(*)"))
5209 "USING INDEX");
5210 else if (Matches("REPACK", MatchAnyExcept("(")))
5211 COMPLETE_WITH("USING INDEX");
5212 else if (Matches("REPACK", "(*)", MatchAnyExcept("(")))
5213 COMPLETE_WITH("USING INDEX");
5214 else if (Matches("REPACK", MatchAny, "USING", "INDEX") ||
5215 Matches("REPACK", "(*)", MatchAny, "USING", "INDEX"))
5216 {
5219 }
5220
5221 /*
5222 * Complete ... [ (*) ] <sth> USING INDEX, with a list of indexes for
5223 * <sth>.
5224 */
5225 else if (TailMatches(MatchAny, "USING", "INDEX"))
5226 {
5229 }
5230 else if (HeadMatches("REPACK", "(*") &&
5231 !HeadMatches("REPACK", "(*)"))
5232 {
5233 /*
5234 * This fires if we're in an unfinished parenthesized option list.
5235 * get_previous_words treats a completed parenthesized option list as
5236 * one word, so the above test is correct.
5237 */
5238 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5239 COMPLETE_WITH("ANALYZE", "CONCURRENTLY", "VERBOSE");
5240 else if (TailMatches("ANALYZE", "CONCURRENTLY", "VERBOSE"))
5241 COMPLETE_WITH("ON", "OFF");
5242 }
5243
5244/* SECURITY LABEL */
5245 else if (Matches("SECURITY"))
5246 COMPLETE_WITH("LABEL");
5247 else if (Matches("SECURITY", "LABEL"))
5248 COMPLETE_WITH("ON", "FOR");
5249 else if (Matches("SECURITY", "LABEL", "FOR", MatchAny))
5250 COMPLETE_WITH("ON");
5251 else if (Matches("SECURITY", "LABEL", "ON") ||
5252 Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
5253 COMPLETE_WITH("TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
5254 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION",
5255 "LARGE OBJECT", "MATERIALIZED VIEW", "LANGUAGE",
5256 "PROPERTY GRAPH", "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
5257 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW");
5258 else if (Matches("SECURITY", "LABEL", "ON", "PROPERTY", "GRAPH"))
5260 else if (Matches("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
5261 COMPLETE_WITH("IS");
5262
5263/* SELECT */
5264 /* naah . . . */
5265
5266/* SET, RESET, SHOW */
5267 /* Complete with a variable name */
5268 else if (TailMatches("SET|RESET") &&
5269 !TailMatches("UPDATE", MatchAny, "SET") &&
5270 !TailMatches("ALTER", "DATABASE|USER|ROLE", MatchAny, "RESET"))
5272 "CONSTRAINTS",
5273 "TRANSACTION",
5274 "SESSION",
5275 "ROLE",
5276 "TABLESPACE",
5277 "ALL");
5278 else if (Matches("SHOW"))
5280 "SESSION AUTHORIZATION",
5281 "ALL");
5282 else if (Matches("SHOW", "SESSION"))
5283 COMPLETE_WITH("AUTHORIZATION");
5284 /* Complete "SET TRANSACTION" */
5285 else if (Matches("SET", "TRANSACTION"))
5286 COMPLETE_WITH("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
5287 else if (Matches("BEGIN|START", "TRANSACTION") ||
5288 Matches("BEGIN", "WORK") ||
5289 Matches("BEGIN") ||
5290 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
5291 COMPLETE_WITH("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
5292 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
5293 Matches("BEGIN", "NOT") ||
5294 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
5295 COMPLETE_WITH("DEFERRABLE");
5296 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
5297 Matches("BEGIN", "ISOLATION") ||
5298 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
5299 COMPLETE_WITH("LEVEL");
5300 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
5301 Matches("BEGIN", "ISOLATION", "LEVEL") ||
5302 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
5303 COMPLETE_WITH("READ", "REPEATABLE READ", "SERIALIZABLE");
5304 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
5305 Matches("BEGIN", "ISOLATION", "LEVEL", "READ") ||
5306 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
5307 COMPLETE_WITH("UNCOMMITTED", "COMMITTED");
5308 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
5309 Matches("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
5310 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
5311 COMPLETE_WITH("READ");
5312 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
5313 Matches("BEGIN", "READ") ||
5314 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
5315 COMPLETE_WITH("ONLY", "WRITE");
5316 /* SET CONSTRAINTS */
5317 else if (Matches("SET", "CONSTRAINTS"))
5319 "ALL");
5320 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
5321 else if (Matches("SET", "CONSTRAINTS", MatchAny))
5322 COMPLETE_WITH("DEFERRED", "IMMEDIATE");
5323 /* Complete SET ROLE */
5324 else if (Matches("SET", "ROLE"))
5326 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
5327 else if (Matches("SET", "SESSION"))
5328 COMPLETE_WITH("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
5329 /* Complete SET SESSION AUTHORIZATION with username */
5330 else if (Matches("SET", "SESSION", "AUTHORIZATION"))
5332 "DEFAULT");
5333 /* Complete RESET SESSION with AUTHORIZATION */
5334 else if (Matches("RESET", "SESSION"))
5335 COMPLETE_WITH("AUTHORIZATION");
5336 /* Complete SET <var> with "TO" */
5337 else if (Matches("SET", MatchAny))
5338 COMPLETE_WITH("TO");
5339
5340 /*
5341 * Complete ALTER DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER ... SET
5342 * <name>
5343 */
5344 else if (Matches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER", MatchAnyN, "SET", MatchAnyExcept("SCHEMA")))
5345 COMPLETE_WITH("FROM CURRENT", "TO");
5346
5347 /*
5348 * Suggest possible variable values in SET variable TO|=, along with the
5349 * preceding ALTER syntaxes.
5350 */
5351 else if (TailMatches("SET", MatchAny, "TO|=") &&
5352 !TailMatches("UPDATE", MatchAny, "SET", MatchAny, "TO|="))
5353 {
5354 /* special cased code for individual GUCs */
5355 if (TailMatches("DateStyle", "TO|="))
5356 COMPLETE_WITH("ISO", "SQL", "Postgres", "German",
5357 "YMD", "DMY", "MDY",
5358 "US", "European", "NonEuropean",
5359 "DEFAULT");
5360 else if (TailMatches("search_path", "TO|="))
5361 {
5362 /* Here, we want to allow pg_catalog, so use narrower exclusion */
5364 " AND nspname NOT LIKE E'pg\\\\_toast%%'"
5365 " AND nspname NOT LIKE E'pg\\\\_temp%%'",
5366 "DEFAULT");
5367 }
5368 else if (TailMatches("TimeZone", "TO|="))
5370 else
5371 {
5372 /* generic, type based, GUC support */
5373 char *guctype = get_guctype(prev2_wd);
5374
5375 /*
5376 * Note: if we don't recognize the GUC name, it's important to not
5377 * offer any completions, as most likely we've misinterpreted the
5378 * context and this isn't a GUC-setting command at all.
5379 */
5380 if (guctype)
5381 {
5382 if (strcmp(guctype, "enum") == 0)
5383 {
5386 "DEFAULT");
5387 }
5388 else if (strcmp(guctype, "bool") == 0)
5389 COMPLETE_WITH("on", "off", "true", "false", "yes", "no",
5390 "1", "0", "DEFAULT");
5391 else
5392 COMPLETE_WITH("DEFAULT");
5393
5394 free(guctype);
5395 }
5396 }
5397 }
5398
5399/* START TRANSACTION */
5400 else if (Matches("START"))
5401 COMPLETE_WITH("TRANSACTION");
5402
5403/* TABLE, but not TABLE embedded in other commands */
5404 else if (Matches("TABLE"))
5406
5407/* TABLESAMPLE */
5408 else if (TailMatches("TABLESAMPLE"))
5410 else if (TailMatches("TABLESAMPLE", MatchAny))
5411 COMPLETE_WITH("(");
5412
5413/* TRUNCATE */
5414 else if (Matches("TRUNCATE"))
5416 "TABLE", "ONLY");
5417 else if (Matches("TRUNCATE", "TABLE"))
5419 "ONLY");
5420 else if (Matches("TRUNCATE", MatchAnyN, "ONLY"))
5422 else if (Matches("TRUNCATE", MatchAny) ||
5423 Matches("TRUNCATE", "TABLE|ONLY", MatchAny) ||
5424 Matches("TRUNCATE", "TABLE", "ONLY", MatchAny))
5425 COMPLETE_WITH("RESTART IDENTITY", "CONTINUE IDENTITY", "CASCADE", "RESTRICT");
5426 else if (Matches("TRUNCATE", MatchAnyN, "IDENTITY"))
5427 COMPLETE_WITH("CASCADE", "RESTRICT");
5428
5429/* UNLISTEN */
5430 else if (Matches("UNLISTEN"))
5432
5433/* UPDATE --- can be inside EXPLAIN, RULE, etc */
5434 /* If prev. word is UPDATE suggest a list of tables */
5435 else if (TailMatches("UPDATE"))
5437 /* Complete UPDATE <table> with "SET" */
5438 else if (TailMatches("UPDATE", MatchAny))
5439 COMPLETE_WITH("SET");
5440 /* Complete UPDATE <table> SET with list of attributes */
5441 else if (TailMatches("UPDATE", MatchAny, "SET"))
5443 /* UPDATE <table> SET <attr> = */
5444 else if (TailMatches("UPDATE", MatchAny, "SET", MatchAnyExcept("*=")))
5445 COMPLETE_WITH("=");
5446
5447/* USER MAPPING */
5448 else if (Matches("ALTER|CREATE|DROP", "USER", "MAPPING"))
5449 COMPLETE_WITH("FOR");
5450 else if (Matches("CREATE", "USER", "MAPPING", "FOR"))
5452 "CURRENT_ROLE",
5453 "CURRENT_USER",
5454 "PUBLIC",
5455 "USER");
5456 else if (Matches("ALTER|DROP", "USER", "MAPPING", "FOR"))
5458 else if (Matches("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
5459 COMPLETE_WITH("SERVER");
5460 else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
5461 COMPLETE_WITH("OPTIONS");
5462
5463/*
5464 * VACUUM [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
5465 * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ [ ONLY ] table_and_columns [, ...] ]
5466 */
5467 else if (Matches("VACUUM"))
5469 "(",
5470 "FULL",
5471 "FREEZE",
5472 "VERBOSE",
5473 "ANALYZE",
5474 "ONLY");
5475 else if (HeadMatches("VACUUM", "(*") &&
5476 !HeadMatches("VACUUM", "(*)"))
5477 {
5478 /*
5479 * This fires if we're in an unfinished parenthesized option list.
5480 * get_previous_words treats a completed parenthesized option list as
5481 * one word, so the above test is correct.
5482 */
5483 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5484 COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
5485 "DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
5486 "INDEX_CLEANUP", "PROCESS_MAIN", "PROCESS_TOAST",
5487 "TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
5488 "ONLY_DATABASE_STATS", "BUFFER_USAGE_LIMIT");
5489 else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_MAIN|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
5490 COMPLETE_WITH("ON", "OFF");
5491 else if (TailMatches("INDEX_CLEANUP"))
5492 COMPLETE_WITH("AUTO", "ON", "OFF");
5493 }
5494 else if (Matches("VACUUM", "(*)"))
5496 "ONLY");
5497 else if (Matches("VACUUM", "FULL"))
5499 "FREEZE",
5500 "VERBOSE",
5501 "ANALYZE",
5502 "ONLY");
5503 else if (Matches("VACUUM", MatchAnyN, "FREEZE"))
5505 "VERBOSE",
5506 "ANALYZE",
5507 "ONLY");
5508 else if (Matches("VACUUM", MatchAnyN, "VERBOSE"))
5510 "ANALYZE",
5511 "ONLY");
5512 else if (Matches("VACUUM", MatchAnyN, "ANALYZE"))
5514 "ONLY");
5515 else if (Matches("VACUUM", MatchAnyN, "("))
5516 /* "VACUUM (" should be caught above, so assume we want columns */
5518 else if (HeadMatches("VACUUM"))
5520
5521/*
5522 * WAIT FOR LSN '<lsn>' [ WITH ( option [, ...] ) ]
5523 * where option can be:
5524 * MODE '<mode>'
5525 * TIMEOUT '<timeout>'
5526 * NO_THROW
5527 * and mode can be:
5528 * standby_replay | standby_write | standby_flush | primary_flush
5529 */
5530 else if (Matches("WAIT"))
5531 COMPLETE_WITH("FOR");
5532 else if (Matches("WAIT", "FOR"))
5533 COMPLETE_WITH("LSN");
5534 else if (Matches("WAIT", "FOR", "LSN"))
5535 /* No completion for LSN value - user must provide manually */
5536 ;
5537 else if (Matches("WAIT", "FOR", "LSN", MatchAny))
5538 COMPLETE_WITH("WITH");
5539 else if (Matches("WAIT", "FOR", "LSN", MatchAny, "WITH"))
5540 COMPLETE_WITH("(");
5541
5542 /*
5543 * Handle parenthesized option list. This fires when we're in an
5544 * unfinished parenthesized option list. get_previous_words treats a
5545 * completed parenthesized option list as one word, so the above test is
5546 * correct.
5547 *
5548 * 'mode' takes a string value (one of the listed above), 'timeout' takes
5549 * a string value, and 'no_throw' takes no value. We do not offer
5550 * completions for the *values* of 'timeout' or 'no_throw'.
5551 */
5552 else if (HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*") &&
5553 !HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*)"))
5554 {
5555 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5556 COMPLETE_WITH("mode", "timeout", "no_throw");
5557 else if (TailMatches("mode"))
5558 COMPLETE_WITH("'standby_replay'", "'standby_write'", "'standby_flush'", "'primary_flush'");
5559 }
5560
5561/* WITH [RECURSIVE] */
5562
5563 /*
5564 * Only match when WITH is the first word, as WITH may appear in many
5565 * other contexts.
5566 */
5567 else if (Matches("WITH"))
5568 COMPLETE_WITH("RECURSIVE");
5569
5570/* WHERE */
5571 /* Simple case of the word before the where being the table name */
5572 else if (TailMatches(MatchAny, "WHERE"))
5574
5575/* ... FROM ... */
5576/* TODO: also include SRF ? */
5577 else if (TailMatches("FROM") && !Matches("COPY|\\copy", MatchAny, "FROM"))
5579
5580/* ... JOIN ... */
5581 else if (TailMatches("JOIN"))
5583 else if (TailMatches("JOIN", MatchAny) && !TailMatches("CROSS|NATURAL", "JOIN", MatchAny))
5584 COMPLETE_WITH("ON", "USING (");
5585 else if (TailMatches("JOIN", MatchAny, MatchAny) &&
5586 !TailMatches("CROSS|NATURAL", "JOIN", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5587 COMPLETE_WITH("ON", "USING (");
5588 else if (TailMatches("JOIN", "LATERAL", MatchAny, MatchAny) &&
5589 !TailMatches("CROSS|NATURAL", "JOIN", "LATERAL", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5590 COMPLETE_WITH("ON", "USING (");
5591 else if (TailMatches("JOIN", MatchAny, "USING") ||
5592 TailMatches("JOIN", MatchAny, MatchAny, "USING") ||
5593 TailMatches("JOIN", "LATERAL", MatchAny, MatchAny, "USING"))
5594 COMPLETE_WITH("(");
5595 else if (TailMatches("JOIN", MatchAny, "USING", "("))
5597 else if (TailMatches("JOIN", MatchAny, MatchAny, "USING", "("))
5599
5600/* ... AT [ LOCAL | TIME ZONE ] ... */
5601 else if (TailMatches("AT"))
5602 COMPLETE_WITH("LOCAL", "TIME ZONE");
5603 else if (TailMatches("AT", "TIME", "ZONE"))
5605
5606/* Backslash commands */
5607/* TODO: \dc \dd \dl */
5608 else if (TailMatchesCS("\\?"))
5609 COMPLETE_WITH_CS("commands", "options", "variables");
5610 else if (TailMatchesCS("\\connect|\\c"))
5611 {
5614 }
5615 else if (TailMatchesCS("\\connect|\\c", MatchAny))
5616 {
5619 }
5620 else if (TailMatchesCS("\\da*"))
5622 else if (TailMatchesCS("\\dAc*", MatchAny) ||
5623 TailMatchesCS("\\dAf*", MatchAny))
5625 else if (TailMatchesCS("\\dAo*", MatchAny) ||
5626 TailMatchesCS("\\dAp*", MatchAny))
5628 else if (TailMatchesCS("\\dA*"))
5630 else if (TailMatchesCS("\\db*"))
5632 else if (TailMatchesCS("\\dconfig*"))
5634 else if (TailMatchesCS("\\dD*"))
5636 else if (TailMatchesCS("\\des*"))
5638 else if (TailMatchesCS("\\deu*"))
5640 else if (TailMatchesCS("\\dew*"))
5642 else if (TailMatchesCS("\\df*"))
5644 else if (HeadMatchesCS("\\df*"))
5646
5647 else if (TailMatchesCS("\\dFd*"))
5649 else if (TailMatchesCS("\\dFp*"))
5651 else if (TailMatchesCS("\\dFt*"))
5653 /* must be at end of \dF alternatives: */
5654 else if (TailMatchesCS("\\dF*"))
5656
5657 else if (TailMatchesCS("\\di*"))
5659 else if (TailMatchesCS("\\dL*"))
5661 else if (TailMatchesCS("\\dn*"))
5663 /* no support for completing operators, but we can complete types: */
5664 else if (HeadMatchesCS("\\do*", MatchAny))
5666 else if (TailMatchesCS("\\dp") || TailMatchesCS("\\z"))
5668 else if (TailMatchesCS("\\dPi*"))
5670 else if (TailMatchesCS("\\dPt*"))
5672 else if (TailMatchesCS("\\dP*"))
5674 else if (TailMatchesCS("\\dRp*"))
5676 else if (TailMatchesCS("\\dRs*"))
5678 else if (TailMatchesCS("\\ds*"))
5680 else if (TailMatchesCS("\\dt*"))
5682 else if (TailMatchesCS("\\dT*"))
5684 else if (TailMatchesCS("\\du*") ||
5685 TailMatchesCS("\\dg*") ||
5686 TailMatchesCS("\\drg*"))
5688 else if (TailMatchesCS("\\dv*"))
5690 else if (TailMatchesCS("\\dx*"))
5692 else if (TailMatchesCS("\\dX*"))
5694 else if (TailMatchesCS("\\dm*"))
5696 else if (TailMatchesCS("\\dE*"))
5698 else if (TailMatchesCS("\\dy*"))
5700
5701 /* must be at end of \d alternatives: */
5702 else if (TailMatchesCS("\\d*"))
5704
5705 else if (TailMatchesCS("\\ef"))
5707 else if (TailMatchesCS("\\ev"))
5709
5710 else if (TailMatchesCS("\\encoding"))
5712 else if (TailMatchesCS("\\h|\\help"))
5714 else if (TailMatchesCS("\\h|\\help", MatchAny))
5715 {
5716 if (TailMatches("DROP"))
5718 else if (TailMatches("ALTER"))
5720
5721 /*
5722 * CREATE is recognized by tail match elsewhere, so doesn't need to be
5723 * repeated here
5724 */
5725 }
5726 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny))
5727 {
5728 if (TailMatches("CREATE|DROP", "ACCESS"))
5729 COMPLETE_WITH("METHOD");
5730 else if (TailMatches("ALTER", "DEFAULT"))
5731 COMPLETE_WITH("PRIVILEGES");
5732 else if (TailMatches("CREATE|ALTER|DROP", "EVENT"))
5733 COMPLETE_WITH("TRIGGER");
5734 else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN"))
5735 COMPLETE_WITH("DATA WRAPPER", "TABLE");
5736 else if (TailMatches("ALTER", "LARGE"))
5737 COMPLETE_WITH("OBJECT");
5738 else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED"))
5739 COMPLETE_WITH("VIEW");
5740 else if (TailMatches("CREATE|ALTER|DROP", "PROPERTY"))
5741 COMPLETE_WITH("GRAPH");
5742 else if (TailMatches("CREATE|ALTER|DROP", "TEXT"))
5743 COMPLETE_WITH("SEARCH");
5744 else if (TailMatches("CREATE|ALTER|DROP", "USER"))
5745 COMPLETE_WITH("MAPPING FOR");
5746 }
5747 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny))
5748 {
5749 if (TailMatches("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
5750 COMPLETE_WITH("WRAPPER");
5751 else if (TailMatches("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
5752 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
5753 else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING"))
5754 COMPLETE_WITH("FOR");
5755 }
5756 else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*"))
5758 else if (TailMatchesCS("\\password"))
5760 else if (TailMatchesCS("\\pset"))
5761 COMPLETE_WITH_CS("border", "columns", "csv_fieldsep",
5762 "display_false", "display_true", "expanded",
5763 "fieldsep", "fieldsep_zero", "footer", "format",
5764 "linestyle", "null", "numericlocale",
5765 "pager", "pager_min_lines",
5766 "recordsep", "recordsep_zero",
5767 "tableattr", "title", "tuples_only",
5768 "unicode_border_linestyle",
5769 "unicode_column_linestyle",
5770 "unicode_header_linestyle",
5771 "xheader_width");
5772 else if (TailMatchesCS("\\pset", MatchAny))
5773 {
5774 if (TailMatchesCS("format"))
5775 COMPLETE_WITH_CS("aligned", "asciidoc", "csv", "html", "latex",
5776 "latex-longtable", "troff-ms", "unaligned",
5777 "wrapped");
5778 else if (TailMatchesCS("xheader_width"))
5779 COMPLETE_WITH_CS("full", "column", "page");
5780 else if (TailMatchesCS("linestyle"))
5781 COMPLETE_WITH_CS("ascii", "old-ascii", "unicode");
5782 else if (TailMatchesCS("pager"))
5783 COMPLETE_WITH_CS("on", "off", "always");
5784 else if (TailMatchesCS("unicode_border_linestyle|"
5785 "unicode_column_linestyle|"
5786 "unicode_header_linestyle"))
5787 COMPLETE_WITH_CS("single", "double");
5788 }
5789 else if (TailMatchesCS("\\unset"))
5790 matches = complete_from_variables(text, "", "", true);
5791 else if (TailMatchesCS("\\set"))
5792 matches = complete_from_variables(text, "", "", false);
5793 else if (TailMatchesCS("\\set", MatchAny))
5794 {
5795 if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|SHOW_ALL_RESULTS|"
5796 "SINGLELINE|SINGLESTEP"))
5797 COMPLETE_WITH_CS("on", "off");
5798 else if (TailMatchesCS("COMP_KEYWORD_CASE"))
5799 COMPLETE_WITH_CS("lower", "upper",
5800 "preserve-lower", "preserve-upper");
5801 else if (TailMatchesCS("ECHO"))
5802 COMPLETE_WITH_CS("errors", "queries", "all", "none");
5803 else if (TailMatchesCS("ECHO_HIDDEN"))
5804 COMPLETE_WITH_CS("noexec", "off", "on");
5805 else if (TailMatchesCS("HISTCONTROL"))
5806 COMPLETE_WITH_CS("ignorespace", "ignoredups",
5807 "ignoreboth", "none");
5808 else if (TailMatchesCS("ON_ERROR_ROLLBACK"))
5809 COMPLETE_WITH_CS("on", "off", "interactive");
5810 else if (TailMatchesCS("SHOW_CONTEXT"))
5811 COMPLETE_WITH_CS("never", "errors", "always");
5812 else if (TailMatchesCS("VERBOSITY"))
5813 COMPLETE_WITH_CS("default", "verbose", "terse", "sqlstate");
5814 }
5815 else if (TailMatchesCS("\\sf*"))
5817 else if (TailMatchesCS("\\sv*"))
5819 else if (TailMatchesCS("\\cd|\\e|\\edit|\\g|\\gx|\\i|\\include|"
5820 "\\ir|\\include_relative|\\o|\\out|"
5821 "\\s|\\w|\\write|\\lo_import") ||
5822 TailMatchesCS("\\lo_export", MatchAny))
5823 COMPLETE_WITH_FILES("\\", false);
5824
5825 /* gen_tabcomplete.pl ends special processing here */
5826 /* END GEN_TABCOMPLETE */
5827
5828 return matches;
5829}
5830
5831
5832/*
5833 * GENERATOR FUNCTIONS
5834 *
5835 * These functions do all the actual work of completing the input. They get
5836 * passed the text so far and the count how many times they have been called
5837 * so far with the same text.
5838 * If you read the above carefully, you'll see that these don't get called
5839 * directly but through the readline interface.
5840 * The return value is expected to be the full completion of the text, going
5841 * through a list each time, or NULL if there are no more matches. The string
5842 * will be free()'d by readline, so you must run it through strdup() or
5843 * something of that sort.
5844 */
5845
5846/*
5847 * Common routine for create_command_generator and drop_command_generator.
5848 * Entries that have 'excluded' flags are not returned.
5849 */
5850static char *
5851create_or_drop_command_generator(const char *text, int state, uint32 excluded)
5852{
5853 static int list_index,
5854 string_length;
5855 const char *name;
5856
5857 /* If this is the first time for this completion, init some values */
5858 if (state == 0)
5859 {
5860 list_index = 0;
5861 string_length = strlen(text);
5862 }
5863
5864 /* find something that matches */
5865 while ((name = words_after_create[list_index++].name))
5866 {
5867 if ((pg_strncasecmp(name, text, string_length) == 0) &&
5868 !(words_after_create[list_index - 1].flags & excluded))
5870 }
5871 /* if nothing matches, return NULL */
5872 return NULL;
5873}
5874
5875/*
5876 * This one gives you one from a list of things you can put after CREATE
5877 * as defined above.
5878 */
5879static char *
5880create_command_generator(const char *text, int state)
5881{
5883}
5884
5885/*
5886 * This function gives you a list of things you can put after a DROP command.
5887 */
5888static char *
5889drop_command_generator(const char *text, int state)
5890{
5892}
5893
5894/*
5895 * This function gives you a list of things you can put after an ALTER command.
5896 */
5897static char *
5898alter_command_generator(const char *text, int state)
5899{
5901}
5902
5903/*
5904 * These functions generate lists using server queries.
5905 * They are all wrappers for _complete_from_query.
5906 */
5907
5908static char *
5909complete_from_query(const char *text, int state)
5910{
5911 /* query is assumed to work for any server version */
5914}
5915
5916static char *
5918{
5920
5921 /* Find appropriate array element */
5922 while (pset.sversion < vquery->min_server_version)
5923 vquery++;
5924 /* Fail completion if server is too old */
5925 if (vquery->query == NULL)
5926 return NULL;
5927
5930}
5931
5932static char *
5933complete_from_schema_query(const char *text, int state)
5934{
5935 /* query is assumed to work for any server version */
5938}
5939
5940static char *
5942{
5944
5945 /* Find appropriate array element */
5946 while (pset.sversion < squery->min_server_version)
5947 squery++;
5948 /* Fail completion if server is too old */
5949 if (squery->catname == NULL)
5950 return NULL;
5951
5954}
5955
5956
5957/*
5958 * This creates a list of matching things, according to a query described by
5959 * the initial arguments. The caller has already done any work needed to
5960 * select the appropriate query for the server's version.
5961 *
5962 * The query can be one of two kinds:
5963 *
5964 * 1. A simple query, which must contain a restriction clause of the form
5965 * output LIKE '%s'
5966 * where "output" is the same string that the query returns. The %s
5967 * will be replaced by a LIKE pattern to match the already-typed text.
5968 * There can be a second '%s', which will be replaced by a suitably-escaped
5969 * version of the string provided in completion_ref_object. If there is a
5970 * third '%s', it will be replaced by a suitably-escaped version of the string
5971 * provided in completion_ref_schema. Those strings should be set up
5972 * by calling set_completion_reference or set_completion_reference_verbatim.
5973 * Simple queries should return a single column of matches. If "verbatim"
5974 * is true, the matches are returned as-is; otherwise, they are taken to
5975 * be SQL identifiers and quoted if necessary.
5976 *
5977 * 2. A schema query used for completion of both schema and relation names.
5978 * This is represented by a SchemaQuery object; see that typedef for details.
5979 *
5980 * See top of file for examples of both kinds of query.
5981 *
5982 * In addition to the query itself, we accept a null-terminated array of
5983 * literal keywords, which will be returned if they match the input-so-far
5984 * (case insensitively). (These are in addition to keywords specified
5985 * within the schema_query, if any.)
5986 *
5987 * If "verbatim" is true, then we use the given text as-is to match the
5988 * query results; otherwise we parse it as a possibly-qualified identifier,
5989 * and reconstruct suitable quoting afterward.
5990 *
5991 * "text" and "state" are supplied by Readline. "text" is the word we are
5992 * trying to complete. "state" is zero on first call, nonzero later.
5993 *
5994 * readline will call this repeatedly with the same text and varying
5995 * state. On each call, we are supposed to return a malloc'd string
5996 * that is a candidate completion. Return NULL when done.
5997 */
5998static char *
6001 const char *const *keywords,
6002 bool verbatim,
6003 const char *text, int state)
6004{
6005 static int list_index,
6008 num_keywords;
6009 static PGresult *result = NULL;
6010 static bool non_empty_object;
6011 static bool schemaquoted;
6012 static bool objectquoted;
6013
6014 /*
6015 * If this is the first time for this completion, we fetch a list of our
6016 * "things" from the backend.
6017 */
6018 if (state == 0)
6019 {
6021 char *schemaname;
6022 char *objectname;
6023 char *e_object_like;
6024 char *e_schemaname;
6025 char *e_ref_object;
6026 char *e_ref_schema;
6027
6028 /* Reset static state, ensuring no memory leaks */
6029 list_index = 0;
6030 num_schema_only = 0;
6031 num_query_other = 0;
6032 num_keywords = 0;
6033 PQclear(result);
6034 result = NULL;
6035
6036 /* Parse text, splitting into schema and object name if needed */
6037 if (verbatim)
6038 {
6040 schemaname = NULL;
6041 }
6042 else
6043 {
6045 &schemaname, &objectname,
6047 }
6048
6049 /* Remember whether the user has typed anything in the object part */
6050 non_empty_object = (*objectname != '\0');
6051
6052 /*
6053 * Convert objectname to a LIKE prefix pattern (e.g. 'foo%'), and set
6054 * up suitably-escaped copies of all the strings we need.
6055 */
6057
6058 if (schemaname)
6059 e_schemaname = escape_string(schemaname);
6060 else
6062
6065 else
6067
6070 else
6072
6074
6075 if (schema_query)
6076 {
6078
6079 /*
6080 * We issue different queries depending on whether the input is
6081 * already qualified or not. schema_query gives us the pieces to
6082 * assemble.
6083 */
6084 if (schemaname == NULL || schema_query->namespace == NULL)
6085 {
6086 /* Get unqualified names matching the input-so-far */
6088 if (schema_query->use_distinct)
6089 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
6091 "%s, NULL::pg_catalog.text FROM %s",
6092 schema_query->result,
6093 schema_query->catname);
6094 if (schema_query->refnamespace && completion_ref_schema)
6096 ", pg_catalog.pg_namespace nr");
6098 if (schema_query->selcondition)
6099 appendPQExpBuffer(&query_buffer, "%s AND ",
6100 schema_query->selcondition);
6101 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s'",
6102 schema_query->result,
6104 if (schema_query->viscondition)
6105 appendPQExpBuffer(&query_buffer, " AND %s",
6106 schema_query->viscondition);
6107 if (schema_query->refname)
6108 {
6110 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
6111 schema_query->refname, e_ref_object);
6112 if (schema_query->refnamespace && completion_ref_schema)
6114 " AND %s = nr.oid AND nr.nspname = '%s'",
6115 schema_query->refnamespace,
6116 e_ref_schema);
6117 else if (schema_query->refviscondition)
6119 " AND %s",
6120 schema_query->refviscondition);
6121 }
6122
6123 /*
6124 * When fetching relation names, suppress system catalogs
6125 * unless the input-so-far begins with "pg_". This is a
6126 * compromise between not offering system catalogs for
6127 * completion at all, and having them swamp the result when
6128 * the input is just "p".
6129 */
6130 if (strcmp(schema_query->catname,
6131 "pg_catalog.pg_class c") == 0 &&
6132 strncmp(objectname, "pg_", 3) != 0)
6133 {
6135 " AND c.relnamespace <> (SELECT oid FROM"
6136 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
6137 }
6138
6139 /*
6140 * If the target object type can be schema-qualified, add in
6141 * schema names matching the input-so-far.
6142 */
6143 if (schema_query->namespace)
6144 {
6145 appendPQExpBuffer(&query_buffer, "\nUNION ALL\n"
6146 "SELECT NULL::pg_catalog.text, n.nspname "
6147 "FROM pg_catalog.pg_namespace n "
6148 "WHERE n.nspname LIKE '%s'",
6150
6151 /*
6152 * Likewise, suppress system schemas unless the
6153 * input-so-far begins with "pg_".
6154 */
6155 if (strncmp(objectname, "pg_", 3) != 0)
6157 " AND n.nspname NOT LIKE E'pg\\\\_%'");
6158
6159 /*
6160 * Since we're matching these schema names to the object
6161 * name, handle their quoting using the object name's
6162 * quoting state.
6163 */
6165 }
6166 }
6167 else
6168 {
6169 /* Input is qualified, so produce only qualified names */
6171 if (schema_query->use_distinct)
6172 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
6173 appendPQExpBuffer(&query_buffer, "%s, n.nspname "
6174 "FROM %s, pg_catalog.pg_namespace n",
6175 schema_query->result,
6176 schema_query->catname);
6177 if (schema_query->refnamespace && completion_ref_schema)
6179 ", pg_catalog.pg_namespace nr");
6180 appendPQExpBuffer(&query_buffer, " WHERE %s = n.oid AND ",
6181 schema_query->namespace);
6182 if (schema_query->selcondition)
6183 appendPQExpBuffer(&query_buffer, "%s AND ",
6184 schema_query->selcondition);
6185 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s' AND ",
6186 schema_query->result,
6188 appendPQExpBuffer(&query_buffer, "n.nspname = '%s'",
6189 e_schemaname);
6190 if (schema_query->refname)
6191 {
6193 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
6194 schema_query->refname, e_ref_object);
6195 if (schema_query->refnamespace && completion_ref_schema)
6197 " AND %s = nr.oid AND nr.nspname = '%s'",
6198 schema_query->refnamespace,
6199 e_ref_schema);
6200 else if (schema_query->refviscondition)
6202 " AND %s",
6203 schema_query->refviscondition);
6204 }
6205 }
6206 }
6207 else
6208 {
6210 /* simple_query is an sprintf-style format string */
6214 }
6215
6216 /* Limit the number of records in the result */
6217 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
6219
6220 /* Finally, we can issue the query */
6222
6223 /* Clean up */
6225 free(schemaname);
6231 }
6232
6233 /* Return the next result, if any, but not if the query failed */
6235 {
6236 int nskip;
6237
6238 while (list_index < PQntuples(result))
6239 {
6240 const char *item = NULL;
6241 const char *nsp = NULL;
6242
6243 if (!PQgetisnull(result, list_index, 0))
6244 item = PQgetvalue(result, list_index, 0);
6245 if (PQnfields(result) > 1 &&
6246 !PQgetisnull(result, list_index, 1))
6247 nsp = PQgetvalue(result, list_index, 1);
6248 list_index++;
6249
6250 /* In verbatim mode, we return all the items as-is */
6251 if (verbatim)
6252 {
6254 return pg_strdup(item);
6255 }
6256
6257 /*
6258 * In normal mode, a name requiring quoting will be returned only
6259 * if the input was empty or quoted. Otherwise the user might see
6260 * completion inserting a quote she didn't type, which is
6261 * surprising. This restriction also dodges some odd behaviors of
6262 * some versions of readline/libedit.
6263 */
6264 if (non_empty_object)
6265 {
6266 if (item && !objectquoted && identifier_needs_quotes(item))
6267 continue;
6269 continue;
6270 }
6271
6272 /* Count schema-only results for hack below */
6273 if (item == NULL && nsp != NULL)
6275 else
6277
6279 }
6280
6281 /*
6282 * When the query result is exhausted, check for hard-wired keywords.
6283 * These will only be returned if they match the input-so-far,
6284 * ignoring case.
6285 */
6286 nskip = list_index - PQntuples(result);
6287 if (schema_query && schema_query->keywords)
6288 {
6289 const char *const *itemp = schema_query->keywords;
6290
6291 while (*itemp)
6292 {
6293 const char *item = *itemp++;
6294
6295 if (nskip-- > 0)
6296 continue;
6297 list_index++;
6298 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6299 {
6300 num_keywords++;
6301 return pg_strdup_keyword_case(item, text);
6302 }
6303 }
6304 }
6305 if (keywords)
6306 {
6307 const char *const *itemp = keywords;
6308
6309 while (*itemp)
6310 {
6311 const char *item = *itemp++;
6312
6313 if (nskip-- > 0)
6314 continue;
6315 list_index++;
6316 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6317 {
6318 num_keywords++;
6319 return pg_strdup_keyword_case(item, text);
6320 }
6321 }
6322 }
6323 }
6324
6325 /*
6326 * Hack: if we returned only bare schema names, don't let Readline add a
6327 * space afterwards. Otherwise the schema will stop being part of the
6328 * completion subject text, which is not what we want.
6329 */
6330 if (num_schema_only > 0 && num_query_other == 0 && num_keywords == 0)
6332
6333 /* No more matches, so free the result structure and return null */
6334 PQclear(result);
6335 result = NULL;
6336 return NULL;
6337}
6338
6339
6340/*
6341 * Set up completion_ref_object and completion_ref_schema
6342 * by parsing the given word. These variables can then be
6343 * used in a query passed to _complete_from_query.
6344 */
6345static void
6346set_completion_reference(const char *word)
6347{
6348 bool schemaquoted,
6350
6354}
6355
6356/*
6357 * Set up completion_ref_object when it should just be
6358 * the given word verbatim.
6359 */
6360static void
6362{
6365}
6366
6367
6368/*
6369 * This function returns in order one of a fixed, NULL pointer terminated list
6370 * of strings (if matching). This can be used if there are only a fixed number
6371 * SQL words that can appear at certain spot.
6372 */
6373static char *
6374complete_from_list(const char *text, int state)
6375{
6376 static int string_length,
6377 list_index,
6378 matches;
6379 static bool casesensitive;
6380 const char *item;
6381
6382 /* need to have a list */
6384
6385 /* Initialization */
6386 if (state == 0)
6387 {
6388 list_index = 0;
6389 string_length = strlen(text);
6391 matches = 0;
6392 }
6393
6394 while ((item = completion_charpp[list_index++]))
6395 {
6396 /* First pass is case sensitive */
6397 if (casesensitive && strncmp(text, item, string_length) == 0)
6398 {
6399 matches++;
6400 return pg_strdup(item);
6401 }
6402
6403 /* Second pass is case insensitive, don't bother counting matches */
6404 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
6405 {
6407 return pg_strdup(item);
6408 else
6409
6410 /*
6411 * If case insensitive matching was requested initially,
6412 * adjust the case according to setting.
6413 */
6414 return pg_strdup_keyword_case(item, text);
6415 }
6416 }
6417
6418 /*
6419 * No matches found. If we're not case insensitive already, lets switch to
6420 * being case insensitive and try again
6421 */
6422 if (casesensitive && matches == 0)
6423 {
6424 casesensitive = false;
6425 list_index = 0;
6426 state++;
6427 return complete_from_list(text, state);
6428 }
6429
6430 /* If no more matches, return null. */
6431 return NULL;
6432}
6433
6434
6435/*
6436 * This function returns one fixed string the first time even if it doesn't
6437 * match what's there, and nothing the second time. The string
6438 * to be used must be in completion_charp.
6439 *
6440 * If the given string is "", this has the effect of preventing readline
6441 * from doing any completion. (Without this, readline tries to do filename
6442 * completion which is seldom the right thing.)
6443 *
6444 * If the given string is not empty, readline will replace whatever the
6445 * user typed with that string. This behavior might be useful if it's
6446 * completely certain that we know what must appear at a certain spot,
6447 * so that it's okay to overwrite misspellings. In practice, given the
6448 * relatively lame parsing technology used in this file, the level of
6449 * certainty is seldom that high, so that you probably don't want to
6450 * use this. Use complete_from_list with a one-element list instead;
6451 * that won't try to auto-correct "misspellings".
6452 */
6453static char *
6454complete_from_const(const char *text, int state)
6455{
6457 if (state == 0)
6458 {
6461 else
6462
6463 /*
6464 * If case insensitive matching was requested initially, adjust
6465 * the case according to setting.
6466 */
6468 }
6469 else
6470 return NULL;
6471}
6472
6473
6474/*
6475 * This function appends the variable name with prefix and suffix to
6476 * the variable names array.
6477 */
6478static void
6479append_variable_names(char ***varnames, int *nvars,
6480 int *maxvars, const char *varname,
6481 const char *prefix, const char *suffix)
6482{
6483 if (*nvars >= *maxvars)
6484 {
6485 *maxvars *= 2;
6486 *varnames = pg_realloc_array(*varnames, char *, (*maxvars) + 1);
6487 }
6488
6489 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
6490}
6491
6492
6493/*
6494 * This function supports completion with the name of a psql variable.
6495 * The variable names can be prefixed and suffixed with additional text
6496 * to support quoting usages. If need_value is true, only variables
6497 * that are currently set are included; otherwise, special variables
6498 * (those that have hooks) are included even if currently unset.
6499 */
6500static char **
6501complete_from_variables(const char *text, const char *prefix, const char *suffix,
6502 bool need_value)
6503{
6504 char **matches;
6505 char **varnames;
6506 int nvars = 0;
6507 int maxvars = 100;
6508 int i;
6509 struct _variable *ptr;
6510
6511 varnames = pg_malloc_array(char *, maxvars + 1);
6512
6513 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
6514 {
6515 if (need_value && !(ptr->value))
6516 continue;
6517 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
6518 prefix, suffix);
6519 }
6520
6521 varnames[nvars] = NULL;
6522 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
6523
6524 for (i = 0; i < nvars; i++)
6525 free(varnames[i]);
6526 free(varnames);
6527
6528 return matches;
6529}
6530
6531
6532/*
6533 * This function returns in order one of a fixed, NULL pointer terminated list
6534 * of string that matches file names or optionally specified list of keywords.
6535 *
6536 * If completion_charpp is set to a null-terminated array of literal keywords,
6537 * those keywords are added to the completion results alongside filenames if
6538 * they case-insensitively match the current input.
6539 */
6540static char *
6541complete_from_files(const char *text, int state)
6542{
6543 static int list_index;
6544 static bool files_done;
6545 const char *item;
6546
6547 /* Initialization */
6548 if (state == 0)
6549 {
6550 list_index = 0;
6551 files_done = false;
6552 }
6553
6554 if (!files_done)
6555 {
6557
6558 /* Return a filename that matches */
6559 if (result)
6560 return result;
6561
6562 /* There are no more matching files */
6563 files_done = true;
6564 }
6565
6566 if (!completion_charpp)
6567 return NULL;
6568
6569 /*
6570 * Check for hard-wired keywords. These will only be returned if they
6571 * match the input-so-far, ignoring case.
6572 */
6573 while ((item = completion_charpp[list_index++]))
6574 {
6575 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6576 {
6577 completion_force_quote = false;
6578 return pg_strdup_keyword_case(item, text);
6579 }
6580 }
6581
6582 return NULL;
6583}
6584
6585/*
6586 * This function wraps rl_filename_completion_function() to strip quotes from
6587 * the input before searching for matches and to quote any matches for which
6588 * the consuming command will require it.
6589 *
6590 * Caller must set completion_charp to a zero- or one-character string
6591 * containing the escape character. This is necessary since \copy has no
6592 * escape character, but every other backslash command recognizes "\" as an
6593 * escape character.
6594 *
6595 * Caller must also set completion_force_quote to indicate whether to force
6596 * quotes around the result. (The SQL COPY command requires that.)
6597 */
6598static char *
6599_complete_from_files(const char *text, int state)
6600{
6601#ifdef USE_FILENAME_QUOTING_FUNCTIONS
6602
6603 /*
6604 * If we're using a version of Readline that supports filename quoting
6605 * hooks, rely on those, and invoke rl_filename_completion_function()
6606 * without messing with its arguments. Readline does stuff internally
6607 * that does not work well at all if we try to handle dequoting here.
6608 * Instead, Readline will call quote_file_name() and dequote_file_name()
6609 * (see below) at appropriate times.
6610 *
6611 * ... or at least, mostly it will. There are some paths involving
6612 * unmatched file names in which Readline never calls quote_file_name(),
6613 * and if left to its own devices it will incorrectly append a quote
6614 * anyway. Set rl_completion_suppress_quote to prevent that. If we do
6615 * get to quote_file_name(), we'll clear this again. (Yes, this seems
6616 * like it's working around Readline bugs.)
6617 */
6618#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
6620#endif
6621
6622 /* If user typed a quote, force quoting (never remove user's quote) */
6623 if (*text == '\'')
6625
6627#else
6628
6629 /*
6630 * Otherwise, we have to do the best we can.
6631 */
6632 static const char *unquoted_text;
6633 char *unquoted_match;
6634 char *ret = NULL;
6635
6636 /* If user typed a quote, force quoting (never remove user's quote) */
6637 if (*text == '\'')
6639
6640 if (state == 0)
6641 {
6642 /* Initialization: stash the unquoted input. */
6644 false, true, pset.encoding);
6645 /* expect a NULL return for the empty string only */
6646 if (!unquoted_text)
6647 {
6648 Assert(*text == '\0');
6650 }
6651 }
6652
6654 if (unquoted_match)
6655 {
6656 struct stat statbuf;
6657 bool is_dir = (stat(unquoted_match, &statbuf) == 0 &&
6658 S_ISDIR(statbuf.st_mode) != 0);
6659
6660 /* Re-quote the result, if needed. */
6661 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
6662 '\'', *completion_charp,
6664 pset.encoding);
6665 if (ret)
6667 else
6668 ret = unquoted_match;
6669
6670 /*
6671 * If it's a directory, replace trailing quote with a slash; this is
6672 * usually more convenient. (If we didn't quote, leave this to
6673 * libedit.)
6674 */
6675 if (*ret == '\'' && is_dir)
6676 {
6677 char *retend = ret + strlen(ret) - 1;
6678
6679 Assert(*retend == '\'');
6680 *retend = '/';
6681 /* Prevent libedit from adding a space, too */
6683 }
6684 }
6685
6686 return ret;
6687#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
6688}
6689
6690
6691/* HELPER FUNCTIONS */
6692
6693
6694/*
6695 * Make a pg_strdup copy of s and convert the case according to
6696 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
6697 */
6698static char *
6699pg_strdup_keyword_case(const char *s, const char *ref)
6700{
6701 char *ret,
6702 *p;
6703 unsigned char first = ref[0];
6704
6705 ret = pg_strdup(s);
6706
6711 {
6712 for (p = ret; *p; p++)
6713 *p = pg_tolower((unsigned char) *p);
6714 }
6715 else
6716 {
6717 for (p = ret; *p; p++)
6718 *p = pg_toupper((unsigned char) *p);
6719 }
6720
6721 return ret;
6722}
6723
6724
6725/*
6726 * escape_string - Escape argument for use as string literal.
6727 *
6728 * The returned value has to be freed.
6729 */
6730static char *
6731escape_string(const char *text)
6732{
6733 size_t text_length;
6734 char *result;
6735
6737
6738 result = pg_malloc(text_length * 2 + 1);
6740
6741 return result;
6742}
6743
6744
6745/*
6746 * make_like_pattern - Convert argument to a LIKE prefix pattern.
6747 *
6748 * We escape _ and % in the given text by backslashing, append a % to
6749 * represent "any subsequent characters", and then pass the string through
6750 * escape_string() so it's ready to insert in a query. The result needs
6751 * to be freed.
6752 */
6753static char *
6754make_like_pattern(const char *word)
6755{
6756 char *result;
6757 char *buffer = pg_malloc(strlen(word) * 2 + 2);
6758 char *bptr = buffer;
6759
6760 while (*word)
6761 {
6762 if (*word == '_' || *word == '%')
6763 *bptr++ = '\\';
6764 if (IS_HIGHBIT_SET(*word))
6765 {
6766 /*
6767 * Transfer multibyte characters without further processing, to
6768 * avoid getting confused in unsafe client encodings.
6769 */
6771
6772 while (chlen-- > 0)
6773 *bptr++ = *word++;
6774 }
6775 else
6776 *bptr++ = *word++;
6777 }
6778 *bptr++ = '%';
6779 *bptr = '\0';
6780
6781 result = escape_string(buffer);
6782 free(buffer);
6783 return result;
6784}
6785
6786
6787/*
6788 * parse_identifier - Parse a possibly-schema-qualified SQL identifier.
6789 *
6790 * This involves splitting off the schema name if present, de-quoting,
6791 * and downcasing any unquoted text. We are a bit laxer than the backend
6792 * in that we allow just portions of a name to be quoted --- that's because
6793 * psql metacommands have traditionally behaved that way.
6794 *
6795 * Outputs are a malloc'd schema name (NULL if none), malloc'd object name,
6796 * and booleans telling whether any part of the schema and object name was
6797 * double-quoted.
6798 */
6799static void
6800parse_identifier(const char *ident,
6801 char **schemaname, char **objectname,
6802 bool *schemaquoted, bool *objectquoted)
6803{
6804 size_t buflen = strlen(ident) + 1;
6806 char *sname;
6807 char *oname;
6808 char *optr;
6809 bool inquotes;
6810
6811 /* Initialize, making a certainly-large-enough output buffer */
6812 sname = NULL;
6813 oname = pg_malloc(buflen);
6814 *schemaquoted = *objectquoted = false;
6815 /* Scan */
6816 optr = oname;
6817 inquotes = false;
6818 while (*ident)
6819 {
6820 unsigned char ch = (unsigned char) *ident++;
6821
6822 if (ch == '"')
6823 {
6824 if (inquotes && *ident == '"')
6825 {
6826 /* two quote marks within a quoted identifier = emit quote */
6827 *optr++ = '"';
6828 ident++;
6829 }
6830 else
6831 {
6832 inquotes = !inquotes;
6833 *objectquoted = true;
6834 }
6835 }
6836 else if (ch == '.' && !inquotes)
6837 {
6838 /* Found a schema name, transfer it to sname / *schemaquoted */
6839 *optr = '\0';
6840 free(sname); /* drop any catalog name */
6841 sname = oname;
6842 oname = pg_malloc(buflen);
6843 optr = oname;
6845 *objectquoted = false;
6846 }
6847 else if (!enc_is_single_byte && IS_HIGHBIT_SET(ch))
6848 {
6849 /*
6850 * Transfer multibyte characters without further processing. They
6851 * wouldn't be affected by our downcasing rule anyway, and this
6852 * avoids possibly doing the wrong thing in unsafe client
6853 * encodings.
6854 */
6856
6857 *optr++ = (char) ch;
6858 while (--chlen > 0)
6859 *optr++ = *ident++;
6860 }
6861 else
6862 {
6863 if (!inquotes)
6864 {
6865 /*
6866 * This downcasing transformation should match the backend's
6867 * downcase_identifier() as best we can. We do not know the
6868 * backend's locale, though, so it's necessarily approximate.
6869 * We assume that psql is operating in the same locale and
6870 * encoding as the backend.
6871 */
6872 if (ch >= 'A' && ch <= 'Z')
6873 ch += 'a' - 'A';
6875 ch = tolower(ch);
6876 }
6877 *optr++ = (char) ch;
6878 }
6879 }
6880
6881 *optr = '\0';
6882 *schemaname = sname;
6883 *objectname = oname;
6884}
6885
6886
6887/*
6888 * requote_identifier - Reconstruct a possibly-schema-qualified SQL identifier.
6889 *
6890 * Build a malloc'd string containing the identifier, with quoting applied
6891 * as necessary. This is more or less the inverse of parse_identifier;
6892 * in particular, if an input component was quoted, we'll quote the output
6893 * even when that isn't strictly required.
6894 *
6895 * Unlike parse_identifier, we handle the case where a schema and no
6896 * object name is provided, producing just "schema.".
6897 */
6898static char *
6899requote_identifier(const char *schemaname, const char *objectname,
6900 bool quote_schema, bool quote_object)
6901{
6902 char *result;
6903 size_t buflen = 1; /* count the trailing \0 */
6904 char *ptr;
6905
6906 /*
6907 * We could use PQescapeIdentifier for some of this, but not all, and it
6908 * adds more notational cruft than it seems worth.
6909 */
6910 if (schemaname)
6911 {
6912 buflen += strlen(schemaname) + 1; /* +1 for the dot */
6913 if (!quote_schema)
6915 if (quote_schema)
6916 {
6917 buflen += 2; /* account for quote marks */
6918 for (const char *p = schemaname; *p; p++)
6919 {
6920 if (*p == '"')
6921 buflen++;
6922 }
6923 }
6924 }
6925 if (objectname)
6926 {
6927 buflen += strlen(objectname);
6928 if (!quote_object)
6930 if (quote_object)
6931 {
6932 buflen += 2; /* account for quote marks */
6933 for (const char *p = objectname; *p; p++)
6934 {
6935 if (*p == '"')
6936 buflen++;
6937 }
6938 }
6939 }
6940 result = pg_malloc(buflen);
6941 ptr = result;
6942 if (schemaname)
6943 {
6944 if (quote_schema)
6945 *ptr++ = '"';
6946 for (const char *p = schemaname; *p; p++)
6947 {
6948 *ptr++ = *p;
6949 if (*p == '"')
6950 *ptr++ = '"';
6951 }
6952 if (quote_schema)
6953 *ptr++ = '"';
6954 *ptr++ = '.';
6955 }
6956 if (objectname)
6957 {
6958 if (quote_object)
6959 *ptr++ = '"';
6960 for (const char *p = objectname; *p; p++)
6961 {
6962 *ptr++ = *p;
6963 if (*p == '"')
6964 *ptr++ = '"';
6965 }
6966 if (quote_object)
6967 *ptr++ = '"';
6968 }
6969 *ptr = '\0';
6970 return result;
6971}
6972
6973
6974/*
6975 * Detect whether an identifier must be double-quoted.
6976 *
6977 * Note we'll quote anything that's not ASCII; the backend's quote_ident()
6978 * does the same. Perhaps this could be relaxed in future.
6979 */
6980static bool
6981identifier_needs_quotes(const char *ident)
6982{
6983 int kwnum;
6984
6985 /* Check syntax. */
6986 if (!((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_'))
6987 return true;
6988 if (strspn(ident, "abcdefghijklmnopqrstuvwxyz0123456789_$") != strlen(ident))
6989 return true;
6990
6991 /*
6992 * Check for keyword. We quote keywords except for unreserved ones.
6993 *
6994 * It is possible that our keyword list doesn't quite agree with the
6995 * server's, but this should be close enough for tab-completion purposes.
6996 *
6997 * Note: ScanKeywordLookup() does case-insensitive comparison, but that's
6998 * fine, since we already know we have all-lower-case.
6999 */
7001
7003 return true;
7004
7005 return false;
7006}
7007
7008
7009/*
7010 * Execute a query, returning NULL if there was any error.
7011 * This should be the preferred way of talking to the database in this file.
7012 */
7013static PGresult *
7014exec_query(const char *query)
7015{
7017
7018 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
7019 return NULL;
7020
7021 result = PQexec(pset.db, query);
7022
7024 {
7025 /*
7026 * Printing an error while the user is typing would be quite annoying,
7027 * so we don't. This does complicate debugging of this code; but you
7028 * can look in the server log instead.
7029 */
7030#ifdef NOT_USED
7031 pg_log_error("tab completion query failed: %s\nQuery was:\n%s",
7032 PQerrorMessage(pset.db), query);
7033#endif
7034 PQclear(result);
7035 result = NULL;
7036 }
7037
7038 return result;
7039}
7040
7041
7042/*
7043 * Parse all the word(s) before point.
7044 *
7045 * Returns a malloc'd array of character pointers that point into the malloc'd
7046 * data array returned to *buffer; caller must free() both of these when done.
7047 * *nwords receives the number of words found, ie, the valid length of the
7048 * return array.
7049 *
7050 * Words are returned right to left, that is, previous_words[0] gets the last
7051 * word before point, previous_words[1] the next-to-last, etc.
7052 */
7053static char **
7054get_previous_words(int point, char **buffer, int *nwords)
7055{
7056 char **previous_words;
7057 char *buf;
7058 char *outptr;
7059 int words_found = 0;
7060 int i;
7061
7062 /*
7063 * If we have anything in tab_completion_query_buf, paste it together with
7064 * rl_line_buffer to construct the full query. Otherwise we can just use
7065 * rl_line_buffer as the input string.
7066 */
7068 {
7070 buf = pg_malloc(point + i + 2);
7072 buf[i++] = '\n';
7074 i += point;
7075 buf[i] = '\0';
7076 /* Readjust point to reference appropriate offset in buf */
7077 point = i;
7078 }
7079 else
7081
7082 /*
7083 * Allocate an array of string pointers and a buffer to hold the strings
7084 * themselves. The worst case is that the line contains only
7085 * non-whitespace WORD_BREAKS characters, making each one a separate word.
7086 * This is usually much more space than we need, but it's cheaper than
7087 * doing a separate malloc() for each word.
7088 */
7090 *buffer = outptr = (char *) pg_malloc(point * 2);
7091
7092 /*
7093 * First we look for a non-word char before the current point. (This is
7094 * probably useless, if readline is on the same page as we are about what
7095 * is a word, but if so it's cheap.)
7096 */
7097 for (i = point - 1; i >= 0; i--)
7098 {
7099 if (strchr(WORD_BREAKS, buf[i]))
7100 break;
7101 }
7102 point = i;
7103
7104 /*
7105 * Now parse words, working backwards, until we hit start of line. The
7106 * backwards scan has some interesting but intentional properties
7107 * concerning parenthesis handling.
7108 */
7109 while (point >= 0)
7110 {
7111 int start,
7112 end;
7113 bool inquotes = false;
7114 int parentheses = 0;
7115
7116 /* now find the first non-space which then constitutes the end */
7117 end = -1;
7118 for (i = point; i >= 0; i--)
7119 {
7120 if (!isspace((unsigned char) buf[i]))
7121 {
7122 end = i;
7123 break;
7124 }
7125 }
7126 /* if no end found, we're done */
7127 if (end < 0)
7128 break;
7129
7130 /*
7131 * Otherwise we now look for the start. The start is either the last
7132 * character before any word-break character going backwards from the
7133 * end, or it's simply character 0. We also handle open quotes and
7134 * parentheses.
7135 */
7136 for (start = end; start > 0; start--)
7137 {
7138 if (buf[start] == '"')
7139 inquotes = !inquotes;
7140 if (!inquotes)
7141 {
7142 if (buf[start] == ')')
7143 parentheses++;
7144 else if (buf[start] == '(')
7145 {
7146 if (--parentheses <= 0)
7147 break;
7148 }
7149 else if (parentheses == 0 &&
7150 strchr(WORD_BREAKS, buf[start - 1]))
7151 break;
7152 }
7153 }
7154
7155 /* Return the word located at start to end inclusive */
7157 i = end - start + 1;
7158 memcpy(outptr, &buf[start], i);
7159 outptr += i;
7160 *outptr++ = '\0';
7161
7162 /* Continue searching */
7163 point = start - 1;
7164 }
7165
7166 /* Release parsing input workspace, if we made one above */
7167 if (buf != rl_line_buffer)
7168 free(buf);
7169
7170 *nwords = words_found;
7171 return previous_words;
7172}
7173
7174/*
7175 * Look up the type for the GUC variable with the passed name.
7176 *
7177 * Returns NULL if the variable is unknown. Otherwise the returned string,
7178 * containing the type, has to be freed.
7179 */
7180static char *
7181get_guctype(const char *varname)
7182{
7184 char *e_varname;
7186 char *guctype = NULL;
7187
7188 e_varname = escape_string(varname);
7189
7192 "SELECT vartype FROM pg_catalog.pg_settings "
7193 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
7194 e_varname);
7195
7198 free(e_varname);
7199
7202
7203 PQclear(result);
7204
7205 return guctype;
7206}
7207
7208#ifdef USE_FILENAME_QUOTING_FUNCTIONS
7209
7210/*
7211 * Quote a filename according to SQL rules, returning a malloc'd string.
7212 * completion_charp must point to escape character or '\0', and
7213 * completion_force_quote must be set correctly, as per comments for
7214 * complete_from_files().
7215 */
7216static char *
7217quote_file_name(char *fname, int match_type, char *quote_pointer)
7218{
7219 char *s;
7220 struct stat statbuf;
7221
7222 /* Quote if needed. */
7223 s = quote_if_needed(fname, " \t\r\n\"`",
7224 '\'', *completion_charp,
7226 pset.encoding);
7227 if (!s)
7228 s = pg_strdup(fname);
7229
7230 /*
7231 * However, some of the time we have to strip the trailing quote from what
7232 * we send back. Never strip the trailing quote if the user already typed
7233 * one; otherwise, suppress the trailing quote if we have multiple/no
7234 * matches (because we don't want to add a quote if the input is seemingly
7235 * unfinished), or if the input was already quoted (because Readline will
7236 * do arguably-buggy things otherwise), or if the file does not exist, or
7237 * if it's a directory.
7238 */
7239 if (*s == '\'' &&
7240 completion_last_char != '\'' &&
7242 (quote_pointer && *quote_pointer == '\'') ||
7243 stat(fname, &statbuf) != 0 ||
7244 S_ISDIR(statbuf.st_mode)))
7245 {
7246 char *send = s + strlen(s) - 1;
7247
7248 Assert(*send == '\'');
7249 *send = '\0';
7250 }
7251
7252 /*
7253 * And now we can let Readline do its thing with possibly adding a quote
7254 * on its own accord. (This covers some additional cases beyond those
7255 * dealt with above.)
7256 */
7257#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
7259#endif
7260
7261 /*
7262 * If user typed a leading quote character other than single quote (i.e.,
7263 * double quote), zap it, so that we replace it with the correct single
7264 * quote.
7265 */
7266 if (quote_pointer && *quote_pointer != '\'')
7267 *quote_pointer = '\0';
7268
7269 return s;
7270}
7271
7272/*
7273 * Dequote a filename, if it's quoted.
7274 * completion_charp must point to escape character or '\0', as per
7275 * comments for complete_from_files().
7276 */
7277static char *
7278dequote_file_name(char *fname, int quote_char)
7279{
7280 char *unquoted_fname;
7281
7282 /*
7283 * If quote_char is set, it's not included in "fname". We have to add it
7284 * or strtokx will not interpret the string correctly (notably, it won't
7285 * recognize escapes).
7286 */
7287 if (quote_char == '\'')
7288 {
7289 char *workspace = (char *) pg_malloc(strlen(fname) + 2);
7290
7291 workspace[0] = quote_char;
7292 strcpy(workspace + 1, fname);
7293 unquoted_fname = strtokx(workspace, "", NULL, "'", *completion_charp,
7294 false, true, pset.encoding);
7295 free(workspace);
7296 }
7297 else
7298 unquoted_fname = strtokx(fname, "", NULL, "'", *completion_charp,
7299 false, true, pset.encoding);
7300
7301 /* expect a NULL return for the empty string only */
7302 if (!unquoted_fname)
7303 {
7304 Assert(*fname == '\0');
7305 unquoted_fname = fname;
7306 }
7307
7308 /* readline expects a malloc'd result that it is to free */
7309 return pg_strdup(unquoted_fname);
7310}
7311
7312#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
7313
7314#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
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition keywords.c:29
Datum arg
Definition elog.c:1323
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:108
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:33
@ 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:2012
#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