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