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 /* ALTER SUBSCRIPTION <name> SKIP ( */
2385 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SKIP", "("))
2386 COMPLETE_WITH("lsn");
2387 /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
2388 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "PUBLICATION"))
2389 {
2390 /* complete with nothing here as this refers to remote publications */
2391 }
2392 /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> */
2393 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN,
2394 "ADD|DROP|SET", "PUBLICATION", MatchAny))
2395 COMPLETE_WITH("WITH (");
2396 /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> WITH ( */
2397 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN,
2398 "ADD|DROP|SET", "PUBLICATION", MatchAny, "WITH", "("))
2399 COMPLETE_WITH("copy_data", "refresh");
2400
2401 /* ALTER SCHEMA <name> */
2402 else if (Matches("ALTER", "SCHEMA", MatchAny))
2403 COMPLETE_WITH("OWNER TO", "RENAME TO");
2404
2405 /* ALTER COLLATION <name> */
2406 else if (Matches("ALTER", "COLLATION", MatchAny))
2407 COMPLETE_WITH("OWNER TO", "REFRESH VERSION", "RENAME TO", "SET SCHEMA");
2408
2409 /* ALTER CONVERSION <name> */
2410 else if (Matches("ALTER", "CONVERSION", MatchAny))
2411 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
2412
2413 /* ALTER DATABASE <name> */
2414 else if (Matches("ALTER", "DATABASE", MatchAny))
2415 COMPLETE_WITH("RESET", "SET", "OWNER TO", "REFRESH COLLATION VERSION", "RENAME TO",
2416 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
2417 "CONNECTION LIMIT");
2418
2419 /* ALTER DATABASE <name> RESET */
2420 else if (Matches("ALTER", "DATABASE", MatchAny, "RESET"))
2421 {
2424 }
2425
2426 /* ALTER DATABASE <name> SET TABLESPACE */
2427 else if (Matches("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE"))
2429
2430 /* ALTER EVENT TRIGGER */
2431 else if (Matches("ALTER", "EVENT", "TRIGGER"))
2433
2434 /* ALTER EVENT TRIGGER <name> */
2435 else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny))
2436 COMPLETE_WITH("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
2437
2438 /* ALTER EVENT TRIGGER <name> ENABLE */
2439 else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
2440 COMPLETE_WITH("REPLICA", "ALWAYS");
2441
2442 /* ALTER EXTENSION <name> */
2443 else if (Matches("ALTER", "EXTENSION", MatchAny))
2444 COMPLETE_WITH("ADD", "DROP", "UPDATE", "SET SCHEMA");
2445
2446 /* ALTER EXTENSION <name> ADD|DROP */
2447 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP"))
2448 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
2449 "CONVERSION", "DOMAIN", "EVENT TRIGGER", "FOREIGN",
2450 "FUNCTION", "MATERIALIZED VIEW", "OPERATOR",
2451 "LANGUAGE", "PROCEDURE", "ROUTINE", "SCHEMA",
2452 "SEQUENCE", "SERVER", "TABLE", "TEXT SEARCH",
2453 "TRANSFORM FOR", "TYPE", "VIEW");
2454
2455 /* ALTER EXTENSION <name> ADD|DROP FOREIGN */
2456 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "FOREIGN"))
2457 COMPLETE_WITH("DATA WRAPPER", "TABLE");
2458
2459 /* ALTER EXTENSION <name> ADD|DROP OPERATOR */
2460 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "OPERATOR"))
2461 COMPLETE_WITH("CLASS", "FAMILY");
2462
2463 /* ALTER EXTENSION <name> ADD|DROP TEXT SEARCH */
2464 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "TEXT", "SEARCH"))
2465 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2466
2467 /* ALTER EXTENSION <name> UPDATE */
2468 else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE"))
2469 COMPLETE_WITH("TO");
2470
2471 /* ALTER EXTENSION <name> UPDATE TO */
2472 else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
2473 {
2476 }
2477
2478 /* ALTER FOREIGN */
2479 else if (Matches("ALTER", "FOREIGN"))
2480 COMPLETE_WITH("DATA WRAPPER", "TABLE");
2481
2482 /* ALTER FOREIGN DATA WRAPPER <name> */
2483 else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2484 COMPLETE_WITH("CONNECTION", "HANDLER", "NO",
2485 "OPTIONS", "OWNER TO", "RENAME TO", "VALIDATOR");
2486 else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny, "NO"))
2487 COMPLETE_WITH("CONNECTION", "HANDLER", "VALIDATOR");
2488
2489 /* ALTER FOREIGN TABLE <name> */
2490 else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny))
2491 COMPLETE_WITH("ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE",
2492 "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO",
2493 "RENAME", "SET", "VALIDATE CONSTRAINT");
2494
2495 /* ALTER INDEX */
2496 else if (Matches("ALTER", "INDEX"))
2498 "ALL IN TABLESPACE");
2499 /* ALTER INDEX <name> */
2500 else if (Matches("ALTER", "INDEX", MatchAny))
2501 COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
2502 "RESET", "ATTACH PARTITION",
2503 "DEPENDS ON EXTENSION", "NO DEPENDS ON EXTENSION");
2504 else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH"))
2505 COMPLETE_WITH("PARTITION");
2506 else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
2508 /* ALTER INDEX <name> ALTER */
2509 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER"))
2510 COMPLETE_WITH("COLUMN");
2511 /* ALTER INDEX <name> ALTER COLUMN */
2512 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN"))
2513 {
2516 }
2517 /* ALTER INDEX <name> ALTER COLUMN <colnum> */
2518 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
2519 COMPLETE_WITH("SET STATISTICS");
2520 /* ALTER INDEX <name> ALTER COLUMN <colnum> SET */
2521 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET"))
2522 COMPLETE_WITH("STATISTICS");
2523 /* ALTER INDEX <name> ALTER COLUMN <colnum> SET STATISTICS */
2524 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS"))
2525 {
2526 /* Enforce no completion here, as an integer has to be specified */
2527 }
2528 /* ALTER INDEX <name> SET */
2529 else if (Matches("ALTER", "INDEX", MatchAny, "SET"))
2530 COMPLETE_WITH("(", "TABLESPACE");
2531 /* ALTER INDEX <name> RESET */
2532 else if (Matches("ALTER", "INDEX", MatchAny, "RESET"))
2533 COMPLETE_WITH("(");
2534 /* ALTER INDEX <foo> SET|RESET ( */
2535 else if (Matches("ALTER", "INDEX", MatchAny, "RESET", "("))
2536 COMPLETE_WITH("fillfactor",
2537 "deduplicate_items", /* BTREE */
2538 "fastupdate", "gin_pending_list_limit", /* GIN */
2539 "buffering", /* GiST */
2540 "pages_per_range", "autosummarize" /* BRIN */
2541 );
2542 else if (Matches("ALTER", "INDEX", MatchAny, "SET", "("))
2543 COMPLETE_WITH("fillfactor =",
2544 "deduplicate_items =", /* BTREE */
2545 "fastupdate =", "gin_pending_list_limit =", /* GIN */
2546 "buffering =", /* GiST */
2547 "pages_per_range =", "autosummarize =" /* BRIN */
2548 );
2549 else if (Matches("ALTER", "INDEX", MatchAny, "NO", "DEPENDS"))
2550 COMPLETE_WITH("ON EXTENSION");
2551 else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS"))
2552 COMPLETE_WITH("ON EXTENSION");
2553
2554 /* ALTER LANGUAGE <name> */
2555 else if (Matches("ALTER", "LANGUAGE", MatchAny))
2556 COMPLETE_WITH("OWNER TO", "RENAME TO");
2557
2558 /* ALTER LARGE OBJECT <oid> */
2559 else if (Matches("ALTER", "LARGE", "OBJECT", MatchAny))
2560 COMPLETE_WITH("OWNER TO");
2561
2562 /* ALTER MATERIALIZED VIEW */
2563 else if (Matches("ALTER", "MATERIALIZED", "VIEW"))
2565 "ALL IN TABLESPACE");
2566
2567 /* ALTER USER,ROLE <name> */
2568 else if (Matches("ALTER", "USER|ROLE", MatchAny) &&
2569 !TailMatches("USER", "MAPPING"))
2570 COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2571 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2572 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2573 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2574 "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
2575 "VALID UNTIL", "WITH");
2576 /* ALTER USER,ROLE <name> IN */
2577 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN"))
2578 COMPLETE_WITH("DATABASE");
2579 /* ALTER USER,ROLE <name> IN DATABASE */
2580 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE"))
2582 /* ALTER USER,ROLE <name> IN DATABASE <dbname> */
2583 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE", MatchAny))
2584 COMPLETE_WITH("SET", "RESET");
2585 /* ALTER USER,ROLE <name> IN DATABASE <dbname> SET */
2586 else if (Matches("ALTER", "USER|ROLE", MatchAny, "IN", "DATABASE", MatchAny, "SET"))
2588 /* XXX missing support for ALTER ROLE <name> IN DATABASE <dbname> RESET */
2589 /* ALTER USER,ROLE <name> RESET */
2590 else if (Matches("ALTER", "USER|ROLE", MatchAny, "RESET"))
2591 {
2594 }
2595
2596 /* ALTER USER,ROLE <name> WITH */
2597 else if (Matches("ALTER", "USER|ROLE", MatchAny, "WITH"))
2598 /* Similar to the above, but don't complete "WITH" again. */
2599 COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2600 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
2601 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2602 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2603 "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
2604 "VALID UNTIL");
2605
2606 /* ALTER DEFAULT PRIVILEGES */
2607 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES"))
2608 COMPLETE_WITH("FOR", "GRANT", "IN SCHEMA", "REVOKE");
2609 /* ALTER DEFAULT PRIVILEGES FOR */
2610 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
2611 COMPLETE_WITH("ROLE");
2612 /* ALTER DEFAULT PRIVILEGES IN */
2613 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
2614 COMPLETE_WITH("SCHEMA");
2615 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
2616 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2617 MatchAny))
2618 COMPLETE_WITH("GRANT", "REVOKE", "IN SCHEMA");
2619 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
2620 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2621 MatchAny))
2622 COMPLETE_WITH("GRANT", "REVOKE", "FOR ROLE");
2623 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
2624 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2625 MatchAny, "FOR"))
2626 COMPLETE_WITH("ROLE");
2627 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
2628 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
2629 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2630 MatchAny, "IN", "SCHEMA", MatchAny) ||
2631 Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2632 MatchAny, "FOR", "ROLE|USER", MatchAny))
2633 COMPLETE_WITH("GRANT", "REVOKE");
2634 /* ALTER DOMAIN <name> */
2635 else if (Matches("ALTER", "DOMAIN", MatchAny))
2636 COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME", "SET",
2637 "VALIDATE CONSTRAINT");
2638 /* ALTER DOMAIN <sth> ADD */
2639 else if (Matches("ALTER", "DOMAIN", MatchAny, "ADD"))
2640 COMPLETE_WITH("CONSTRAINT", "NOT NULL", "CHECK (");
2641 /* ALTER DOMAIN <sth> ADD CONSTRAINT <sth> */
2642 else if (Matches("ALTER", "DOMAIN", MatchAny, "ADD", "CONSTRAINT", MatchAny))
2643 COMPLETE_WITH("NOT NULL", "CHECK (");
2644 /* ALTER DOMAIN <sth> DROP */
2645 else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP"))
2646 COMPLETE_WITH("CONSTRAINT", "DEFAULT", "NOT NULL");
2647 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
2648 else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
2649 {
2652 }
2653 /* ALTER DOMAIN <sth> RENAME */
2654 else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME"))
2655 COMPLETE_WITH("CONSTRAINT", "TO");
2656 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
2657 else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
2658 COMPLETE_WITH("TO");
2659
2660 /* ALTER DOMAIN <sth> SET */
2661 else if (Matches("ALTER", "DOMAIN", MatchAny, "SET"))
2662 COMPLETE_WITH("DEFAULT", "NOT NULL", "SCHEMA");
2663 /* ALTER SEQUENCE <name> */
2664 else if (Matches("ALTER", "SEQUENCE", MatchAny))
2665 COMPLETE_WITH("AS", "INCREMENT", "MINVALUE", "MAXVALUE", "RESTART",
2666 "START", "NO", "CACHE", "CYCLE", "SET", "OWNED BY",
2667 "OWNER TO", "RENAME TO");
2668 /* ALTER SEQUENCE <name> AS */
2669 else if (TailMatches("ALTER", "SEQUENCE", MatchAny, "AS"))
2670 COMPLETE_WITH_CS("smallint", "integer", "bigint");
2671 /* ALTER SEQUENCE <name> NO */
2672 else if (Matches("ALTER", "SEQUENCE", MatchAny, "NO"))
2673 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
2674 /* ALTER SEQUENCE <name> SET */
2675 else if (Matches("ALTER", "SEQUENCE", MatchAny, "SET"))
2676 COMPLETE_WITH("SCHEMA", "LOGGED", "UNLOGGED");
2677 /* ALTER SERVER <name> */
2678 else if (Matches("ALTER", "SERVER", MatchAny))
2679 COMPLETE_WITH("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
2680 /* ALTER SERVER <name> VERSION <version> */
2681 else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
2682 COMPLETE_WITH("OPTIONS");
2683 /* ALTER SYSTEM SET, RESET, RESET ALL */
2684 else if (Matches("ALTER", "SYSTEM"))
2685 COMPLETE_WITH("SET", "RESET");
2686 else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
2688 "ALL");
2689 else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
2690 COMPLETE_WITH("TO");
2691 /* ALTER VIEW <name> */
2692 else if (Matches("ALTER", "VIEW", MatchAny))
2693 COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME", "RESET", "SET");
2694 /* ALTER VIEW xxx RENAME */
2695 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME"))
2696 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
2697 else if (Matches("ALTER", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
2699 /* ALTER VIEW xxx ALTER [ COLUMN ] yyy */
2700 else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
2701 Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
2702 COMPLETE_WITH("SET DEFAULT", "DROP DEFAULT");
2703 /* ALTER VIEW xxx RENAME yyy */
2704 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
2705 COMPLETE_WITH("TO");
2706 /* ALTER VIEW xxx RENAME COLUMN yyy */
2707 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
2708 COMPLETE_WITH("TO");
2709 /* ALTER VIEW xxx RESET ( */
2710 else if (Matches("ALTER", "VIEW", MatchAny, "RESET"))
2711 COMPLETE_WITH("(");
2712 /* Complete ALTER VIEW xxx SET with "(" or "SCHEMA" */
2713 else if (Matches("ALTER", "VIEW", MatchAny, "SET"))
2714 COMPLETE_WITH("(", "SCHEMA");
2715 /* ALTER VIEW xxx SET|RESET ( yyy [= zzz] ) */
2716 else if (Matches("ALTER", "VIEW", MatchAny, "SET|RESET", "("))
2718 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", MatchAny))
2719 COMPLETE_WITH("=");
2720 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "check_option", "="))
2721 COMPLETE_WITH("local", "cascaded");
2722 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "security_barrier|security_invoker", "="))
2723 COMPLETE_WITH("true", "false");
2724
2725 /* ALTER MATERIALIZED VIEW <name> */
2726 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
2727 COMPLETE_WITH("ALTER COLUMN", "CLUSTER ON", "DEPENDS ON EXTENSION",
2728 "NO DEPENDS ON EXTENSION", "OWNER TO", "RENAME",
2729 "RESET (", "SET");
2730 /* ALTER MATERIALIZED VIEW xxx RENAME */
2731 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME"))
2732 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
2733 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
2735 /* ALTER MATERIALIZED VIEW xxx RENAME yyy */
2736 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
2737 COMPLETE_WITH("TO");
2738 /* ALTER MATERIALIZED VIEW xxx RENAME COLUMN yyy */
2739 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
2740 COMPLETE_WITH("TO");
2741 /* ALTER MATERIALIZED VIEW xxx SET */
2742 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET"))
2743 COMPLETE_WITH("(", "ACCESS METHOD", "SCHEMA", "TABLESPACE", "WITHOUT CLUSTER");
2744 /* ALTER MATERIALIZED VIEW xxx SET ACCESS METHOD */
2745 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET", "ACCESS", "METHOD"))
2747
2748 /* ALTER POLICY <name> */
2749 else if (Matches("ALTER", "POLICY"))
2751 /* ALTER POLICY <name> ON */
2752 else if (Matches("ALTER", "POLICY", MatchAny))
2753 COMPLETE_WITH("ON");
2754 /* ALTER POLICY <name> ON <table> */
2755 else if (Matches("ALTER", "POLICY", MatchAny, "ON"))
2756 {
2759 }
2760 /* ALTER POLICY <name> ON <table> - show options */
2761 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny))
2762 COMPLETE_WITH("RENAME TO", "TO", "USING (", "WITH CHECK (");
2763 /* ALTER POLICY <name> ON <table> TO <role> */
2764 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2767 /* ALTER POLICY <name> ON <table> USING ( */
2768 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2769 COMPLETE_WITH("(");
2770 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
2771 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
2772 COMPLETE_WITH("(");
2773
2774 /* ALTER PROPERTY GRAPH */
2775 else if (Matches("ALTER", "PROPERTY", "GRAPH"))
2777 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny))
2778 COMPLETE_WITH("ADD", "ALTER", "DROP", "OWNER TO", "RENAME TO", "SET SCHEMA");
2779 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD|ALTER|DROP"))
2780 COMPLETE_WITH("VERTEX", "EDGE");
2781 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD|DROP", "VERTEX|EDGE"))
2782 COMPLETE_WITH("TABLES");
2783 else if (HeadMatches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ADD") && TailMatches("EDGE"))
2784 COMPLETE_WITH("TABLES");
2785 else if (Matches("ALTER", "PROPERTY", "GRAPH", MatchAny, "ALTER", "VERTEX|EDGE"))
2786 COMPLETE_WITH("TABLE");
2787
2788 /* ALTER RULE <name>, add ON */
2789 else if (Matches("ALTER", "RULE", MatchAny))
2790 COMPLETE_WITH("ON");
2791
2792 /* If we have ALTER RULE <name> ON, then add the correct tablename */
2793 else if (Matches("ALTER", "RULE", MatchAny, "ON"))
2794 {
2797 }
2798
2799 /* ALTER RULE <name> ON <name> */
2800 else if (Matches("ALTER", "RULE", MatchAny, "ON", MatchAny))
2801 COMPLETE_WITH("RENAME TO");
2802
2803 /* ALTER STATISTICS <name> */
2804 else if (Matches("ALTER", "STATISTICS", MatchAny))
2805 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA", "SET STATISTICS");
2806 /* ALTER STATISTICS <name> SET */
2807 else if (Matches("ALTER", "STATISTICS", MatchAny, "SET"))
2808 COMPLETE_WITH("SCHEMA", "STATISTICS");
2809
2810 /* ALTER TRIGGER <name>, add ON */
2811 else if (Matches("ALTER", "TRIGGER", MatchAny))
2812 COMPLETE_WITH("ON");
2813
2814 else if (Matches("ALTER", "TRIGGER", MatchAny, "ON"))
2815 {
2818 }
2819
2820 /* ALTER TRIGGER <name> ON <name> */
2821 else if (Matches("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
2822 COMPLETE_WITH("RENAME TO", "DEPENDS ON EXTENSION",
2823 "NO DEPENDS ON EXTENSION");
2824
2825 /*
2826 * If we detect ALTER TABLE <name>, suggest sub commands
2827 */
2828 else if (Matches("ALTER", "TABLE", MatchAny))
2829 COMPLETE_WITH("ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP",
2830 "ENABLE", "INHERIT", "NO", "RENAME", "RESET",
2831 "OWNER TO", "SET", "VALIDATE CONSTRAINT",
2832 "REPLICA IDENTITY", "ATTACH PARTITION",
2833 "DETACH PARTITION", "FORCE ROW LEVEL SECURITY",
2834 "SPLIT PARTITION", "MERGE PARTITIONS (",
2835 "OF", "NOT OF");
2836 /* ALTER TABLE xxx ADD */
2837 else if (Matches("ALTER", "TABLE", MatchAny, "ADD"))
2838 {
2839 /*
2840 * make sure to keep this list and the MatchAnyExcept() below in sync
2841 */
2842 COMPLETE_WITH("COLUMN", "CONSTRAINT", "CHECK (", "NOT NULL", "UNIQUE",
2843 "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
2844 }
2845 /* ALTER TABLE xxx ADD [COLUMN] yyy */
2846 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN", MatchAny) ||
2847 Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAnyExcept("COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|NOT|EXCLUDE|FOREIGN")))
2849 /* ALTER TABLE xxx ADD CONSTRAINT yyy */
2850 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny))
2851 COMPLETE_WITH("CHECK (", "NOT NULL", "UNIQUE", "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
2852 /* ALTER TABLE xxx ADD NOT NULL */
2853 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "NOT", "NULL"))
2855 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "NOT", "NULL"))
2857 /* ALTER TABLE xxx ADD [CONSTRAINT yyy] (PRIMARY KEY|UNIQUE) */
2858 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY") ||
2859 Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE") ||
2860 Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "PRIMARY", "KEY") ||
2861 Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "UNIQUE"))
2862 COMPLETE_WITH("(", "USING INDEX");
2863 /* ALTER TABLE xxx ADD PRIMARY KEY USING INDEX */
2864 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY", "USING", "INDEX"))
2865 {
2868 }
2869 /* ALTER TABLE xxx ADD UNIQUE USING INDEX */
2870 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE", "USING", "INDEX"))
2871 {
2874 }
2875 /* ALTER TABLE xxx ADD CONSTRAINT yyy PRIMARY KEY USING INDEX */
2876 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2877 "PRIMARY", "KEY", "USING", "INDEX"))
2878 {
2881 }
2882 /* ALTER TABLE xxx ADD CONSTRAINT yyy UNIQUE USING INDEX */
2883 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2884 "UNIQUE", "USING", "INDEX"))
2885 {
2888 }
2889 /* ALTER TABLE xxx ENABLE */
2890 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE"))
2891 COMPLETE_WITH("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
2892 "TRIGGER");
2893 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
2894 COMPLETE_WITH("RULE", "TRIGGER");
2895 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
2896 {
2899 }
2900 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
2901 {
2904 }
2905 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
2906 {
2909 }
2910 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
2911 {
2914 }
2915 /* ALTER TABLE xxx INHERIT */
2916 else if (Matches("ALTER", "TABLE", MatchAny, "INHERIT"))
2918 /* ALTER TABLE xxx NO */
2919 else if (Matches("ALTER", "TABLE", MatchAny, "NO"))
2920 COMPLETE_WITH("FORCE ROW LEVEL SECURITY", "INHERIT");
2921 /* ALTER TABLE xxx NO INHERIT */
2922 else if (Matches("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
2924 /* ALTER TABLE xxx DISABLE */
2925 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE"))
2926 COMPLETE_WITH("ROW LEVEL SECURITY", "RULE", "TRIGGER");
2927 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
2928 {
2931 }
2932 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
2933 {
2936 }
2937
2938 /* ALTER TABLE xxx ALTER */
2939 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER"))
2940 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT");
2941
2942 /* ALTER TABLE xxx RENAME */
2943 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME"))
2944 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT", "TO");
2945 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
2947
2948 /* ALTER TABLE xxx RENAME yyy */
2949 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
2950 COMPLETE_WITH("TO");
2951
2952 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
2953 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
2954 COMPLETE_WITH("TO");
2955
2956 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
2957 else if (Matches("ALTER", "TABLE", MatchAny, "DROP"))
2958 COMPLETE_WITH("COLUMN", "CONSTRAINT");
2959 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
2960 else if (Matches("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
2962 /* ALTER TABLE <sth> ALTER|DROP|RENAME CONSTRAINT <constraint> */
2963 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME", "CONSTRAINT"))
2964 {
2967 }
2968 /* ALTER TABLE <sth> VALIDATE CONSTRAINT <non-validated constraint> */
2969 else if (Matches("ALTER", "TABLE", MatchAny, "VALIDATE", "CONSTRAINT"))
2970 {
2973 }
2974 /* ALTER TABLE ALTER [COLUMN] <foo> */
2975 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
2976 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
2977 COMPLETE_WITH("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
2978 /* ALTER TABLE ALTER [COLUMN] <foo> ADD */
2979 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD") ||
2980 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD"))
2981 COMPLETE_WITH("GENERATED");
2982 /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
2983 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED") ||
2984 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED"))
2985 COMPLETE_WITH("ALWAYS", "BY DEFAULT");
2986 /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
2987 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2988 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2989 Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT") ||
2990 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT"))
2991 COMPLETE_WITH("AS IDENTITY");
2992 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
2993 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
2994 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
2995 COMPLETE_WITH("(", "COMPRESSION", "DATA TYPE", "DEFAULT", "EXPRESSION", "GENERATED", "NOT NULL",
2996 "STATISTICS", "STORAGE",
2997 /* a subset of ALTER SEQUENCE options */
2998 "INCREMENT", "MINVALUE", "MAXVALUE", "START", "NO", "CACHE", "CYCLE");
2999 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
3000 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
3001 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
3002 COMPLETE_WITH("n_distinct", "n_distinct_inherited");
3003 /* ALTER TABLE ALTER [COLUMN] <foo> SET COMPRESSION */
3004 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "COMPRESSION") ||
3005 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "COMPRESSION"))
3006 COMPLETE_WITH("DEFAULT", "PGLZ", "LZ4");
3007 /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION */
3008 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION") ||
3009 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION"))
3010 COMPLETE_WITH("AS");
3011 /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION AS */
3012 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION", "AS") ||
3013 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION", "AS"))
3014 COMPLETE_WITH("(");
3015 /* ALTER TABLE ALTER [COLUMN] <foo> SET GENERATED */
3016 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "GENERATED") ||
3017 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "GENERATED"))
3018 COMPLETE_WITH("ALWAYS", "BY DEFAULT");
3019 /* ALTER TABLE ALTER [COLUMN] <foo> SET NO */
3020 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "NO") ||
3021 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "NO"))
3022 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
3023 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
3024 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
3025 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
3026 COMPLETE_WITH("DEFAULT", "PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
3027 /* ALTER TABLE ALTER [COLUMN] <foo> SET STATISTICS */
3028 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS") ||
3029 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STATISTICS"))
3030 {
3031 /* Enforce no completion here, as an integer has to be specified */
3032 }
3033 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
3034 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
3035 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
3036 COMPLETE_WITH("DEFAULT", "EXPRESSION", "IDENTITY", "NOT NULL");
3037 else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER"))
3038 COMPLETE_WITH("ON");
3039 else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
3040 {
3043 }
3044 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
3045 else if (Matches("ALTER", "TABLE", MatchAny, "SET"))
3046 COMPLETE_WITH("(", "ACCESS METHOD", "LOGGED", "SCHEMA",
3047 "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT");
3048
3049 /*
3050 * If we have ALTER TABLE <sth> SET ACCESS METHOD provide a list of table
3051 * AMs.
3052 */
3053 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "ACCESS", "METHOD"))
3055 "DEFAULT");
3056
3057 /*
3058 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
3059 * tablespaces
3060 */
3061 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
3063 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
3064 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
3065 COMPLETE_WITH("CLUSTER", "OIDS");
3066 /* ALTER TABLE <foo> RESET */
3067 else if (Matches("ALTER", "TABLE", MatchAny, "RESET"))
3068 COMPLETE_WITH("(");
3069 /* ALTER TABLE <foo> SET|RESET ( */
3070 else if (Matches("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
3072 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
3073 {
3076 }
3077 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
3078 COMPLETE_WITH("INDEX");
3079 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
3080 COMPLETE_WITH("FULL", "NOTHING", "DEFAULT", "USING");
3081 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA"))
3082 COMPLETE_WITH("IDENTITY");
3083
3084 /*
3085 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
3086 * tables.
3087 */
3088 else if (Matches("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
3090 /* Limited completion support for partition bound specification */
3091 else if (TailMatches("ATTACH", "PARTITION", MatchAny))
3092 COMPLETE_WITH("FOR VALUES", "DEFAULT");
3093 else if (TailMatches("FOR", "VALUES"))
3094 COMPLETE_WITH("FROM (", "IN (", "WITH (");
3095
3096 /*
3097 * If we have ALTER TABLE <foo> DETACH|SPLIT PARTITION, provide a list of
3098 * partitions of <foo>.
3099 */
3100 else if (Matches("ALTER", "TABLE", MatchAny, "DETACH|SPLIT", "PARTITION"))
3101 {
3104 }
3105 else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION", MatchAny))
3106 COMPLETE_WITH("CONCURRENTLY", "FINALIZE");
3107
3108 /* ALTER TABLE <name> SPLIT PARTITION <name> */
3109 else if (Matches("ALTER", "TABLE", MatchAny, "SPLIT", "PARTITION", MatchAny))
3110 COMPLETE_WITH("INTO ( PARTITION");
3111
3112 /* ALTER TABLE <name> MERGE PARTITIONS ( */
3113 else if (Matches("ALTER", "TABLE", MatchAny, "MERGE", "PARTITIONS", "("))
3114 {
3117 }
3118 else if (Matches("ALTER", "TABLE", MatchAny, "MERGE", "PARTITIONS", "(*)"))
3119 COMPLETE_WITH("INTO");
3120
3121 /* ALTER TABLE <name> OF */
3122 else if (Matches("ALTER", "TABLE", MatchAny, "OF"))
3124
3125 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
3126 else if (Matches("ALTER", "TABLESPACE", MatchAny))
3127 COMPLETE_WITH("RENAME TO", "OWNER TO", "SET", "RESET");
3128 /* ALTER TABLESPACE <foo> SET|RESET */
3129 else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
3130 COMPLETE_WITH("(");
3131 /* ALTER TABLESPACE <foo> SET|RESET ( */
3132 else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
3133 COMPLETE_WITH("seq_page_cost", "random_page_cost",
3134 "effective_io_concurrency", "maintenance_io_concurrency");
3135
3136 /* ALTER TEXT SEARCH */
3137 else if (Matches("ALTER", "TEXT", "SEARCH"))
3138 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3139 else if (Matches("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
3140 COMPLETE_WITH("RENAME TO", "SET SCHEMA");
3141 else if (Matches("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
3142 COMPLETE_WITH("(", "OWNER TO", "RENAME TO", "SET SCHEMA");
3143 else if (Matches("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
3144 COMPLETE_WITH("ADD MAPPING FOR", "ALTER MAPPING",
3145 "DROP MAPPING FOR",
3146 "OWNER TO", "RENAME TO", "SET SCHEMA");
3147
3148 /* complete ALTER TYPE <foo> with actions */
3149 else if (Matches("ALTER", "TYPE", MatchAny))
3150 COMPLETE_WITH("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
3151 "DROP ATTRIBUTE",
3152 "OWNER TO", "RENAME", "SET SCHEMA", "SET (");
3153 /* complete ALTER TYPE <foo> ADD with actions */
3154 else if (Matches("ALTER", "TYPE", MatchAny, "ADD"))
3155 COMPLETE_WITH("ATTRIBUTE", "VALUE");
3156 /* ALTER TYPE <foo> RENAME */
3157 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME"))
3158 COMPLETE_WITH("ATTRIBUTE", "TO", "VALUE");
3159 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
3160 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
3161 COMPLETE_WITH("TO");
3162 /* ALTER TYPE xxx RENAME ATTRIBUTE yyy TO zzz */
3163 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny, "TO", MatchAny))
3164 COMPLETE_WITH("CASCADE", "RESTRICT");
3165
3166 /*
3167 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
3168 * of attributes
3169 */
3170 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
3172 /* complete ALTER TYPE ADD ATTRIBUTE <foo> with list of types */
3173 else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny))
3175 /* complete ALTER TYPE ADD ATTRIBUTE <foo> <footype> with CASCADE/RESTRICT */
3176 else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny, MatchAny))
3177 COMPLETE_WITH("CASCADE", "RESTRICT");
3178 /* complete ALTER TYPE DROP ATTRIBUTE <foo> with CASCADE/RESTRICT */
3179 else if (Matches("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE", MatchAny))
3180 COMPLETE_WITH("CASCADE", "RESTRICT");
3181 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
3182 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
3183 COMPLETE_WITH("TYPE");
3184 /* ALTER TYPE ALTER ATTRIBUTE <foo> TYPE <footype> */
3185 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny, "TYPE", MatchAny))
3186 COMPLETE_WITH("CASCADE", "RESTRICT");
3187 /* complete ALTER TYPE <sth> RENAME VALUE with list of enum values */
3188 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
3190 /* ALTER TYPE <foo> SET */
3191 else if (Matches("ALTER", "TYPE", MatchAny, "SET"))
3192 COMPLETE_WITH("(", "SCHEMA");
3193 /* complete ALTER TYPE <foo> SET ( with settable properties */
3194 else if (Matches("ALTER", "TYPE", MatchAny, "SET", "("))
3195 COMPLETE_WITH("ANALYZE", "RECEIVE", "SEND", "STORAGE", "SUBSCRIPT",
3196 "TYPMOD_IN", "TYPMOD_OUT");
3197
3198 /* complete ALTER GROUP <foo> */
3199 else if (Matches("ALTER", "GROUP", MatchAny))
3200 COMPLETE_WITH("ADD USER", "DROP USER", "RENAME TO");
3201 /* complete ALTER GROUP <foo> ADD|DROP with USER */
3202 else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP"))
3203 COMPLETE_WITH("USER");
3204 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
3205 else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
3207
3208/*
3209 * ANALYZE [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
3210 * ANALYZE [ VERBOSE ] [ [ ONLY ] table_and_columns [, ...] ]
3211 */
3212 else if (Matches("ANALYZE"))
3214 "(", "VERBOSE", "ONLY");
3215 else if (Matches("ANALYZE", "VERBOSE"))
3217 "ONLY");
3218 else if (HeadMatches("ANALYZE", "(*") &&
3219 !HeadMatches("ANALYZE", "(*)"))
3220 {
3221 /*
3222 * This fires if we're in an unfinished parenthesized option list.
3223 * get_previous_words treats a completed parenthesized option list as
3224 * one word, so the above test is correct.
3225 */
3226 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3227 COMPLETE_WITH("VERBOSE", "SKIP_LOCKED", "BUFFER_USAGE_LIMIT");
3228 else if (TailMatches("VERBOSE|SKIP_LOCKED"))
3229 COMPLETE_WITH("ON", "OFF");
3230 }
3231 else if (Matches("ANALYZE", "(*)"))
3233 "ONLY");
3234 else if (Matches("ANALYZE", MatchAnyN, "("))
3235 /* "ANALYZE (" should be caught above, so assume we want columns */
3237 else if (HeadMatches("ANALYZE"))
3239
3240/* BEGIN */
3241 else if (Matches("BEGIN"))
3242 COMPLETE_WITH("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3243/* END, ABORT */
3244 else if (Matches("END|ABORT"))
3245 COMPLETE_WITH("AND", "WORK", "TRANSACTION");
3246/* COMMIT */
3247 else if (Matches("COMMIT"))
3248 COMPLETE_WITH("AND", "WORK", "TRANSACTION", "PREPARED");
3249/* RELEASE SAVEPOINT */
3250 else if (Matches("RELEASE"))
3251 COMPLETE_WITH("SAVEPOINT");
3252/* ROLLBACK */
3253 else if (Matches("ROLLBACK"))
3254 COMPLETE_WITH("AND", "WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
3255 else if (Matches("ABORT|END|COMMIT|ROLLBACK", "AND"))
3256 COMPLETE_WITH("CHAIN");
3257/* CALL */
3258 else if (Matches("CALL"))
3260 else if (Matches("CALL", MatchAny))
3261 COMPLETE_WITH("(");
3262/* CHECKPOINT */
3263 else if (Matches("CHECKPOINT"))
3264 COMPLETE_WITH("(");
3265 else if (HeadMatches("CHECKPOINT", "(*") &&
3266 !HeadMatches("CHECKPOINT", "(*)"))
3267 {
3268 /*
3269 * This fires if we're in an unfinished parenthesized option list.
3270 * get_previous_words treats a completed parenthesized option list as
3271 * one word, so the above test is correct.
3272 */
3273 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3274 COMPLETE_WITH("MODE", "FLUSH_UNLOGGED");
3275 else if (TailMatches("MODE"))
3276 COMPLETE_WITH("FAST", "SPREAD");
3277 }
3278/* CLOSE */
3279 else if (Matches("CLOSE"))
3281 "ALL");
3282/* CLUSTER */
3283 else if (Matches("CLUSTER"))
3285 "VERBOSE");
3286 else if (Matches("CLUSTER", "VERBOSE") ||
3287 Matches("CLUSTER", "(*)"))
3289 /* If we have CLUSTER <sth>, then add "USING" */
3290 else if (Matches("CLUSTER", MatchAnyExcept("VERBOSE|ON|(|(*)")))
3291 COMPLETE_WITH("USING");
3292 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
3293 else if (Matches("CLUSTER", "VERBOSE|(*)", MatchAny))
3294 COMPLETE_WITH("USING");
3295 /* If we have CLUSTER <sth> USING, then add the index as well */
3296 else if (Matches("CLUSTER", MatchAny, "USING") ||
3297 Matches("CLUSTER", "VERBOSE|(*)", MatchAny, "USING"))
3298 {
3301 }
3302 else if (HeadMatches("CLUSTER", "(*") &&
3303 !HeadMatches("CLUSTER", "(*)"))
3304 {
3305 /*
3306 * This fires if we're in an unfinished parenthesized option list.
3307 * get_previous_words treats a completed parenthesized option list as
3308 * one word, so the above test is correct.
3309 */
3310 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3311 COMPLETE_WITH("VERBOSE");
3312 }
3313
3314/* COMMENT */
3315 else if (Matches("COMMENT"))
3316 COMPLETE_WITH("ON");
3317 else if (Matches("COMMENT", "ON"))
3318 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
3319 "COLUMN", "CONSTRAINT", "CONVERSION", "DATABASE",
3320 "DOMAIN", "EXTENSION", "EVENT TRIGGER",
3321 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
3322 "FUNCTION", "INDEX", "LANGUAGE", "LARGE OBJECT",
3323 "MATERIALIZED VIEW", "OPERATOR", "POLICY",
3324 "PROCEDURE", "PROCEDURAL LANGUAGE", "PROPERTY GRAPH", "PUBLICATION", "ROLE",
3325 "ROUTINE", "RULE", "SCHEMA", "SEQUENCE", "SERVER",
3326 "STATISTICS", "SUBSCRIPTION", "TABLE",
3327 "TABLESPACE", "TEXT SEARCH", "TRANSFORM FOR",
3328 "TRIGGER", "TYPE", "VIEW");
3329 else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
3331 else if (Matches("COMMENT", "ON", "CONSTRAINT"))
3333 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny))
3334 COMPLETE_WITH("ON");
3335 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
3336 {
3339 "DOMAIN");
3340 }
3341 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON", "DOMAIN"))
3343 else if (Matches("COMMENT", "ON", "EVENT", "TRIGGER"))
3345 else if (Matches("COMMENT", "ON", "FOREIGN"))
3346 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3347 else if (Matches("COMMENT", "ON", "FOREIGN", "TABLE"))
3349 else if (Matches("COMMENT", "ON", "MATERIALIZED", "VIEW"))
3351 else if (Matches("COMMENT", "ON", "POLICY"))
3353 else if (Matches("COMMENT", "ON", "POLICY", MatchAny))
3354 COMPLETE_WITH("ON");
3355 else if (Matches("COMMENT", "ON", "POLICY", MatchAny, "ON"))
3356 {
3359 }
3360 else if (Matches("COMMENT", "ON", "PROCEDURAL", "LANGUAGE"))
3362 else if (Matches("COMMENT", "ON", "PROPERTY", "GRAPH"))
3364 else if (Matches("COMMENT", "ON", "RULE", MatchAny))
3365 COMPLETE_WITH("ON");
3366 else if (Matches("COMMENT", "ON", "RULE", MatchAny, "ON"))
3367 {
3370 }
3371 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH"))
3372 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3373 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "CONFIGURATION"))
3375 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "DICTIONARY"))
3377 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "PARSER"))
3379 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "TEMPLATE"))
3381 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR"))
3383 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny))
3384 COMPLETE_WITH("LANGUAGE");
3385 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3386 {
3389 }
3390 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny))
3391 COMPLETE_WITH("ON");
3392 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny, "ON"))
3393 {
3396 }
3397 else if (Matches("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
3398 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3399 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3400 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
3401 COMPLETE_WITH("IS");
3402
3403/* COPY */
3404
3405 /*
3406 * If we have COPY, offer list of tables or "(" (Also cover the analogous
3407 * backslash command).
3408 */
3409 else if (Matches("COPY|\\copy"))
3411 /* Complete COPY ( with legal query commands */
3412 else if (Matches("COPY|\\copy", "("))
3413 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "MERGE INTO", "WITH");
3414 /* Complete COPY <sth> */
3415 else if (Matches("COPY|\\copy", MatchAny))
3416 COMPLETE_WITH("FROM", "TO");
3417 /* Complete COPY|\copy <sth> FROM|TO with filename or STDIN/STDOUT/PROGRAM */
3418 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO"))
3419 {
3420 if (HeadMatches("COPY"))
3421 {
3422 /* COPY requires quoted filename */
3423 if (TailMatches("FROM"))
3424 COMPLETE_WITH_FILES_PLUS("", true, "STDIN", "PROGRAM");
3425 else
3426 COMPLETE_WITH_FILES_PLUS("", true, "STDOUT", "PROGRAM");
3427 }
3428 else
3429 {
3430 /* \copy supports pstdin and pstdout */
3431 if (TailMatches("FROM"))
3432 COMPLETE_WITH_FILES_PLUS("", false, "STDIN", "PSTDIN", "PROGRAM");
3433 else
3434 COMPLETE_WITH_FILES_PLUS("", false, "STDOUT", "PSTDOUT", "PROGRAM");
3435 }
3436 }
3437
3438 /* Complete COPY|\copy <sth> FROM|TO PROGRAM */
3439 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM"))
3440 COMPLETE_WITH_FILES("", HeadMatches("COPY")); /* COPY requires quoted
3441 * filename */
3442
3443 /* Complete COPY <sth> TO [PROGRAM] <sth> */
3444 else if (Matches("COPY|\\copy", MatchAny, "TO", MatchAnyExcept("PROGRAM")) ||
3445 Matches("COPY|\\copy", MatchAny, "TO", "PROGRAM", MatchAny))
3446 COMPLETE_WITH("WITH (");
3447
3448 /* Complete COPY <sth> FROM [PROGRAM] <sth> */
3449 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM")) ||
3450 Matches("COPY|\\copy", MatchAny, "FROM", "PROGRAM", MatchAny))
3451 COMPLETE_WITH("WITH (", "WHERE");
3452
3453 /* Complete COPY <sth> FROM|TO [PROGRAM] filename WITH ( */
3454 else if (HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*") ||
3455 HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*"))
3456 {
3457 if (!HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*)") &&
3458 !HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*)"))
3459 {
3460 /*
3461 * This fires if we're in an unfinished parenthesized option list.
3462 * get_previous_words treats a completed parenthesized option list
3463 * as one word, so the above tests are correct.
3464 */
3465
3466 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3467 {
3468 if (HeadMatches("COPY|\\copy", MatchAny, "FROM"))
3470 else
3472 }
3473
3474 /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
3475 else if (TailMatches("FORMAT"))
3476 COMPLETE_WITH("binary", "csv", "text", "json");
3477
3478 /* Complete COPY <sth> FROM|TO filename WITH (FREEZE */
3479 else if (TailMatches("FREEZE"))
3480 COMPLETE_WITH("true", "false");
3481
3482 /* Complete COPY <sth> FROM|TO filename WITH (HEADER */
3483 else if (TailMatches("HEADER"))
3484 COMPLETE_WITH("true", "false", "MATCH");
3485
3486 /* Complete COPY <sth> FROM filename WITH (ON_ERROR */
3487 else if (TailMatches("ON_ERROR"))
3488 COMPLETE_WITH("stop", "ignore", "set_null");
3489
3490 /* Complete COPY <sth> FROM filename WITH (LOG_VERBOSITY */
3491 else if (TailMatches("LOG_VERBOSITY"))
3492 COMPLETE_WITH("silent", "default", "verbose");
3493 }
3494
3495 /* A completed parenthesized option list should be caught below */
3496 }
3497
3498 /* Complete COPY <sth> FROM [PROGRAM] <sth> WITH (<options>) */
3499 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM"), "WITH", MatchAny) ||
3500 Matches("COPY|\\copy", MatchAny, "FROM", "PROGRAM", MatchAny, "WITH", MatchAny))
3501 COMPLETE_WITH("WHERE");
3502
3503 /* CREATE ACCESS METHOD */
3504 /* Complete "CREATE ACCESS METHOD <name>" */
3505 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny))
3506 COMPLETE_WITH("TYPE");
3507 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
3508 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
3509 COMPLETE_WITH("INDEX", "TABLE");
3510 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
3511 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
3512 COMPLETE_WITH("HANDLER");
3513
3514 /* CREATE COLLATION */
3515 else if (Matches("CREATE", "COLLATION", MatchAny))
3516 COMPLETE_WITH("(", "FROM");
3517 else if (Matches("CREATE", "COLLATION", MatchAny, "FROM"))
3519 else if (HeadMatches("CREATE", "COLLATION", MatchAny, "(*"))
3520 {
3521 if (TailMatches("(|*,"))
3522 COMPLETE_WITH("LOCALE =", "LC_COLLATE =", "LC_CTYPE =",
3523 "PROVIDER =", "DETERMINISTIC =");
3524 else if (TailMatches("PROVIDER", "="))
3525 COMPLETE_WITH("libc", "icu");
3526 else if (TailMatches("DETERMINISTIC", "="))
3527 COMPLETE_WITH("true", "false");
3528 }
3529
3530 /* CREATE DATABASE */
3531 else if (Matches("CREATE", "DATABASE", MatchAny))
3532 COMPLETE_WITH("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
3533 "IS_TEMPLATE", "STRATEGY",
3534 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
3535 "LC_COLLATE", "LC_CTYPE", "LOCALE", "OID",
3536 "LOCALE_PROVIDER", "ICU_LOCALE");
3537
3538 else if (Matches("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
3540 else if (Matches("CREATE", "DATABASE", MatchAny, "STRATEGY"))
3541 COMPLETE_WITH("WAL_LOG", "FILE_COPY");
3542
3543 /* CREATE DOMAIN --- is allowed inside CREATE SCHEMA, so use TailMatches */
3544 else if (TailMatches("CREATE", "DOMAIN", MatchAny))
3545 COMPLETE_WITH("AS");
3546 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "AS"))
3548 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
3549 COMPLETE_WITH("COLLATE", "DEFAULT", "CONSTRAINT",
3550 "NOT NULL", "NULL", "CHECK (");
3551 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
3553
3554 /* CREATE EXTENSION */
3555 /* Complete with available extensions rather than installed ones. */
3556 else if (Matches("CREATE", "EXTENSION"))
3558 /* CREATE EXTENSION <name> */
3559 else if (Matches("CREATE", "EXTENSION", MatchAny))
3560 COMPLETE_WITH("WITH SCHEMA", "CASCADE", "VERSION");
3561 /* CREATE EXTENSION <name> VERSION */
3562 else if (Matches("CREATE", "EXTENSION", MatchAny, "VERSION"))
3563 {
3566 }
3567
3568 /* CREATE FOREIGN */
3569 else if (Matches("CREATE", "FOREIGN"))
3570 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3571
3572 /* CREATE FOREIGN DATA WRAPPER */
3573 else if (Matches("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
3574 COMPLETE_WITH("CONNECTION", "HANDLER", "OPTIONS", "VALIDATOR");
3575
3576 /* CREATE FOREIGN TABLE */
3577 else if (Matches("CREATE", "FOREIGN", "TABLE", MatchAny))
3578 COMPLETE_WITH("(", "PARTITION OF");
3579
3580 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
3581 /* First off we complete CREATE UNIQUE with "INDEX" */
3582 else if (TailMatches("CREATE", "UNIQUE"))
3583 COMPLETE_WITH("INDEX");
3584
3585 /*
3586 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
3587 * existing indexes
3588 */
3589 else if (TailMatches("CREATE|UNIQUE", "INDEX"))
3591 "ON", "CONCURRENTLY");
3592
3593 /*
3594 * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
3595 * that indexes can be created on
3596 */
3597 else if (TailMatches("INDEX|CONCURRENTLY", MatchAny, "ON") ||
3598 TailMatches("INDEX|CONCURRENTLY", "ON"))
3600
3601 /*
3602 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
3603 * indexes
3604 */
3605 else if (TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
3607 "ON");
3608 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
3609 else if (TailMatches("CREATE|UNIQUE", "INDEX", MatchAny) ||
3610 TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
3611 COMPLETE_WITH("ON");
3612
3613 /*
3614 * Complete INDEX <name> ON <table> with a list of table columns (which
3615 * should really be in parens)
3616 */
3617 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny) ||
3618 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny))
3619 COMPLETE_WITH("(", "USING");
3620 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny, "(") ||
3621 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
3623 /* same if you put in USING */
3624 else if (TailMatches("ON", MatchAny, "USING", MatchAny, "("))
3626 /* Complete USING with an index method */
3627 else if (TailMatches("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
3628 TailMatches("INDEX", MatchAny, "ON", MatchAny, "USING") ||
3629 TailMatches("INDEX", "ON", MatchAny, "USING"))
3631 else if (TailMatches("ON", MatchAny, "USING", MatchAny) &&
3634 COMPLETE_WITH("(");
3635
3636 /* CREATE OR REPLACE */
3637 else if (Matches("CREATE", "OR"))
3638 COMPLETE_WITH("REPLACE");
3639
3640 /* CREATE POLICY */
3641 /* Complete "CREATE POLICY <name> ON" */
3642 else if (Matches("CREATE", "POLICY", MatchAny))
3643 COMPLETE_WITH("ON");
3644 /* Complete "CREATE POLICY <name> ON <table>" */
3645 else if (Matches("CREATE", "POLICY", MatchAny, "ON"))
3647 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
3648 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny))
3649 COMPLETE_WITH("AS", "FOR", "TO", "USING (", "WITH CHECK (");
3650 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
3651 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
3652 COMPLETE_WITH("PERMISSIVE", "RESTRICTIVE");
3653
3654 /*
3655 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3656 * FOR|TO|USING|WITH CHECK
3657 */
3658 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
3659 COMPLETE_WITH("FOR", "TO", "USING", "WITH CHECK");
3660 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
3661 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
3662 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3663 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
3664 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
3665 COMPLETE_WITH("TO", "WITH CHECK (");
3666 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
3667 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
3668 COMPLETE_WITH("TO", "USING (");
3669 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
3670 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
3671 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3672 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
3673 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
3676 /* Complete "CREATE POLICY <name> ON <table> USING (" */
3677 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
3678 COMPLETE_WITH("(");
3679
3680 /*
3681 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3682 * ALL|SELECT|INSERT|UPDATE|DELETE
3683 */
3684 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
3685 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3686
3687 /*
3688 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3689 * INSERT TO|WITH CHECK"
3690 */
3691 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
3692 COMPLETE_WITH("TO", "WITH CHECK (");
3693
3694 /*
3695 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3696 * SELECT|DELETE TO|USING"
3697 */
3698 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
3699 COMPLETE_WITH("TO", "USING (");
3700
3701 /*
3702 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3703 * ALL|UPDATE TO|USING|WITH CHECK
3704 */
3705 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
3706 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3707
3708 /*
3709 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
3710 * <role>"
3711 */
3712 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
3715
3716 /*
3717 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3718 * USING ("
3719 */
3720 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
3721 COMPLETE_WITH("(");
3722
3723/* CREATE PROPERTY GRAPH */
3724 else if (Matches("CREATE", "PROPERTY"))
3725 COMPLETE_WITH("GRAPH");
3726 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny))
3727 COMPLETE_WITH("VERTEX");
3728 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE"))
3729 COMPLETE_WITH("TABLES");
3730 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES"))
3731 COMPLETE_WITH("(");
3732 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES", "("))
3734 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES", "(*)"))
3735 COMPLETE_WITH("EDGE");
3736 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP"))
3737 COMPLETE_WITH("TABLES");
3738 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP", "TABLES"))
3739 COMPLETE_WITH("(");
3740 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP", "TABLES", "("))
3742
3743/* CREATE PUBLICATION */
3744 else if (Matches("CREATE", "PUBLICATION", MatchAny))
3745 COMPLETE_WITH("FOR TABLE", "FOR TABLES IN SCHEMA", "FOR ALL TABLES", "FOR ALL SEQUENCES", "WITH (");
3746 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
3747 COMPLETE_WITH("TABLE", "TABLES IN SCHEMA", "ALL TABLES", "ALL SEQUENCES");
3748 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL"))
3749 COMPLETE_WITH("TABLES", "SEQUENCES");
3750 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
3751 COMPLETE_WITH("EXCEPT ( TABLE", "WITH (");
3752 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT"))
3753 COMPLETE_WITH("( TABLE");
3754 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "("))
3755 COMPLETE_WITH("TABLE");
3756 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE"))
3758 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd, ','))
3760 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd, ','))
3761 COMPLETE_WITH(")");
3762 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES"))
3763 COMPLETE_WITH("IN SCHEMA");
3764 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) && !ends_with(prev_wd, ','))
3765 COMPLETE_WITH("WHERE (", "WITH (");
3766 /* Complete "CREATE PUBLICATION <name> FOR TABLE" with "<table>, ..." */
3767 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE"))
3769
3770 /*
3771 * "CREATE PUBLICATION <name> FOR TABLE <name> WHERE (" - complete with
3772 * table attributes
3773 */
3774 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE"))
3775 COMPLETE_WITH("(");
3776 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "("))
3778 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "(*)"))
3779 COMPLETE_WITH(" WITH (");
3780
3781 /*
3782 * Complete "CREATE PUBLICATION <name> FOR TABLES IN SCHEMA <schema>, ..."
3783 */
3784 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA"))
3786 " AND nspname NOT LIKE E'pg\\\\_%%'",
3787 "CURRENT_SCHEMA");
3788 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA", MatchAny) && (!ends_with(prev_wd, ',')))
3789 COMPLETE_WITH("WITH (");
3790 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
3791 else if (Matches("CREATE", "PUBLICATION", MatchAnyN, "WITH", "("))
3792 COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root");
3793
3794/* CREATE RULE */
3795 /* Complete "CREATE [ OR REPLACE ] RULE <sth>" with "AS ON" */
3796 else if (Matches("CREATE", "RULE", MatchAny) ||
3797 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny))
3798 COMPLETE_WITH("AS ON");
3799 /* Complete "CREATE [ OR REPLACE ] RULE <sth> AS" with "ON" */
3800 else if (Matches("CREATE", "RULE", MatchAny, "AS") ||
3801 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS"))
3802 COMPLETE_WITH("ON");
3803
3804 /*
3805 * Complete "CREATE [ OR REPLACE ] RULE <sth> AS ON" with
3806 * SELECT|UPDATE|INSERT|DELETE
3807 */
3808 else if (Matches("CREATE", "RULE", MatchAny, "AS", "ON") ||
3809 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS", "ON"))
3810 COMPLETE_WITH("SELECT", "UPDATE", "INSERT", "DELETE");
3811 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
3812 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
3813 COMPLETE_WITH("TO");
3814 /* Complete "AS ON <sth> TO" with a table name */
3815 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
3817
3818/* CREATE SCHEMA [ <name> ] [ AUTHORIZATION ] */
3819 else if (Matches("CREATE", "SCHEMA"))
3821 "AUTHORIZATION");
3822 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION") ||
3823 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION"))
3826 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION", MatchAny) ||
3827 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION", MatchAny))
3828 COMPLETE_WITH("CREATE", "GRANT");
3829 else if (Matches("CREATE", "SCHEMA", MatchAny))
3830 COMPLETE_WITH("AUTHORIZATION", "CREATE", "GRANT");
3831
3832/* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3833 else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
3834 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
3835 COMPLETE_WITH("AS", "INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
3836 "CACHE", "CYCLE", "OWNED BY", "START WITH");
3837 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "AS") ||
3838 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "AS"))
3839 COMPLETE_WITH_CS("smallint", "integer", "bigint");
3840 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "NO") ||
3841 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
3842 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
3843
3844/* CREATE SERVER <name> */
3845 else if (Matches("CREATE", "SERVER", MatchAny))
3846 COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
3847
3848/* CREATE STATISTICS <name> */
3849 else if (Matches("CREATE", "STATISTICS", MatchAny))
3850 COMPLETE_WITH("(", "ON");
3851 else if (Matches("CREATE", "STATISTICS", MatchAny, "("))
3852 COMPLETE_WITH("ndistinct", "dependencies", "mcv");
3853 else if (Matches("CREATE", "STATISTICS", MatchAny, "(*)"))
3854 COMPLETE_WITH("ON");
3855 else if (Matches("CREATE", "STATISTICS", MatchAny, MatchAnyN, "FROM"))
3857
3858/* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3859 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
3860 else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
3861 COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW");
3862 /* Complete "CREATE UNLOGGED" with TABLE or SEQUENCE */
3863 else if (TailMatches("CREATE", "UNLOGGED"))
3864 COMPLETE_WITH("TABLE", "SEQUENCE");
3865 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
3866 else if (TailMatches("PARTITION", "BY"))
3867 COMPLETE_WITH("RANGE (", "LIST (", "HASH (");
3868 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
3869 else if (TailMatches("PARTITION", "OF"))
3871 /* Limited completion support for partition bound specification */
3872 else if (TailMatches("PARTITION", "OF", MatchAny))
3873 COMPLETE_WITH("FOR VALUES", "DEFAULT");
3874 /* Complete CREATE TABLE <name> with '(', AS, OF or PARTITION OF */
3875 else if (TailMatches("CREATE", "TABLE", MatchAny) ||
3876 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny))
3877 COMPLETE_WITH("(", "AS", "OF", "PARTITION OF");
3878 /* Complete CREATE TABLE <name> OF with list of composite types */
3879 else if (TailMatches("CREATE", "TABLE", MatchAny, "OF") ||
3880 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "OF"))
3882 /* Complete CREATE TABLE <name> [ (...) ] AS with list of keywords */
3883 else if (TailMatches("CREATE", "TABLE", MatchAny, "AS") ||
3884 TailMatches("CREATE", "TABLE", MatchAny, "(*)", "AS") ||
3885 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "AS") ||
3886 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "AS"))
3887 COMPLETE_WITH("EXECUTE", "SELECT", "TABLE", "VALUES", "WITH");
3888 /* Complete CREATE TABLE name (...) with supported options */
3889 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)"))
3890 COMPLETE_WITH("AS", "INHERITS (", "PARTITION BY", "USING", "TABLESPACE", "WITH (");
3891 else if (TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)"))
3892 COMPLETE_WITH("AS", "INHERITS (", "USING", "TABLESPACE", "WITH (");
3893 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)"))
3894 COMPLETE_WITH("AS", "INHERITS (", "ON COMMIT", "PARTITION BY", "USING",
3895 "TABLESPACE", "WITH (");
3896 /* Complete CREATE TABLE (...) USING with table access methods */
3897 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "USING") ||
3898 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "USING"))
3900 /* Complete CREATE TABLE (...) WITH with storage parameters */
3901 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "WITH", "(") ||
3902 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "WITH", "("))
3904 /* Complete CREATE TABLE ON COMMIT with actions */
3905 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)", "ON", "COMMIT"))
3906 COMPLETE_WITH("DELETE ROWS", "DROP", "PRESERVE ROWS");
3907
3908/* CREATE TABLESPACE */
3909 else if (Matches("CREATE", "TABLESPACE", MatchAny))
3910 COMPLETE_WITH("OWNER", "LOCATION");
3911 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
3912 else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
3913 COMPLETE_WITH("LOCATION");
3914
3915/* CREATE TEXT SEARCH --- is allowed inside CREATE SCHEMA, so use TailMatches */
3916 else if (TailMatches("CREATE", "TEXT", "SEARCH"))
3917 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3918 else if (TailMatches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
3919 COMPLETE_WITH("(");
3920
3921/* CREATE TRANSFORM */
3922 else if (Matches("CREATE", "TRANSFORM") ||
3923 Matches("CREATE", "OR", "REPLACE", "TRANSFORM"))
3924 COMPLETE_WITH("FOR");
3925 else if (Matches("CREATE", "TRANSFORM", "FOR") ||
3926 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR"))
3928 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny) ||
3929 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny))
3930 COMPLETE_WITH("LANGUAGE");
3931 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE") ||
3932 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3933 {
3936 }
3937
3938/* CREATE SUBSCRIPTION */
3939 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny))
3940 COMPLETE_WITH("CONNECTION", "SERVER");
3941 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER"))
3943 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER", MatchAny))
3944 COMPLETE_WITH("PUBLICATION");
3945 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
3946 COMPLETE_WITH("PUBLICATION");
3947 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER",
3948 MatchAny, "PUBLICATION"))
3949 {
3950 /* complete with nothing here as this refers to remote publications */
3951 }
3952 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
3953 MatchAny, "PUBLICATION"))
3954 {
3955 /* complete with nothing here as this refers to remote publications */
3956 }
3957 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "PUBLICATION", MatchAny))
3958 COMPLETE_WITH("WITH (");
3959 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
3960 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "WITH", "("))
3961 COMPLETE_WITH("binary", "connect", "copy_data", "create_slot",
3962 "disable_on_error", "enabled", "failover",
3963 "max_retention_duration", "origin",
3964 "password_required", "retain_dead_tuples",
3965 "run_as_owner", "slot_name", "streaming",
3966 "synchronous_commit", "two_phase");
3967
3968/* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
3969
3970 /*
3971 * Complete CREATE [ OR REPLACE ] TRIGGER <name> with BEFORE|AFTER|INSTEAD
3972 * OF.
3973 */
3974 else if (TailMatches("CREATE", "TRIGGER", MatchAny) ||
3975 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny))
3976 COMPLETE_WITH("BEFORE", "AFTER", "INSTEAD OF");
3977
3978 /*
3979 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER with an
3980 * event.
3981 */
3982 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER") ||
3983 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
3984 COMPLETE_WITH("INSERT", "DELETE", "UPDATE", "TRUNCATE");
3985 /* Complete CREATE [ OR REPLACE ] TRIGGER <name> INSTEAD OF with an event */
3986 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF") ||
3987 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
3988 COMPLETE_WITH("INSERT", "DELETE", "UPDATE");
3989
3990 /*
3991 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER sth with
3992 * OR|ON.
3993 */
3994 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3995 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3996 TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny) ||
3997 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
3998 COMPLETE_WITH("ON", "OR");
3999
4000 /*
4001 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER event ON
4002 * with a list of tables. EXECUTE FUNCTION is the recommended grammar
4003 * instead of EXECUTE PROCEDURE in version 11 and upwards.
4004 */
4005 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON") ||
4006 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
4008
4009 /*
4010 * Complete CREATE [ OR REPLACE ] TRIGGER ... INSTEAD OF event ON with a
4011 * list of views.
4012 */
4013 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON") ||
4014 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
4016 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4017 "ON", MatchAny) ||
4018 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4019 "ON", MatchAny))
4020 {
4021 if (pset.sversion >= 110000)
4022 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
4023 "REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
4024 else
4025 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
4026 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4027 }
4028 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4029 "DEFERRABLE") ||
4030 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4031 "DEFERRABLE") ||
4032 Matches("CREATE", "TRIGGER", MatchAnyN,
4033 "INITIALLY", "IMMEDIATE|DEFERRED") ||
4034 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4035 "INITIALLY", "IMMEDIATE|DEFERRED"))
4036 {
4037 if (pset.sversion >= 110000)
4038 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
4039 else
4040 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4041 }
4042 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4043 "REFERENCING") ||
4044 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4045 "REFERENCING"))
4046 COMPLETE_WITH("OLD TABLE", "NEW TABLE");
4047 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4048 "OLD|NEW", "TABLE") ||
4049 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4050 "OLD|NEW", "TABLE"))
4051 COMPLETE_WITH("AS");
4052 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4053 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
4054 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4055 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
4056 Matches("CREATE", "TRIGGER", MatchAnyN,
4057 "REFERENCING", "OLD", "TABLE", MatchAny) ||
4058 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4059 "REFERENCING", "OLD", "TABLE", MatchAny))
4060 {
4061 if (pset.sversion >= 110000)
4062 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
4063 else
4064 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4065 }
4066 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4067 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
4068 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4069 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
4070 Matches("CREATE", "TRIGGER", MatchAnyN,
4071 "REFERENCING", "NEW", "TABLE", MatchAny) ||
4072 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4073 "REFERENCING", "NEW", "TABLE", MatchAny))
4074 {
4075 if (pset.sversion >= 110000)
4076 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
4077 else
4078 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4079 }
4080 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4081 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4082 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4083 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4084 Matches("CREATE", "TRIGGER", MatchAnyN,
4085 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4086 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4087 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4088 Matches("CREATE", "TRIGGER", MatchAnyN,
4089 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4090 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4091 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4092 Matches("CREATE", "TRIGGER", MatchAnyN,
4093 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4094 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4095 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny))
4096 {
4097 if (pset.sversion >= 110000)
4098 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE FUNCTION");
4099 else
4100 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE PROCEDURE");
4101 }
4102 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4103 "FOR") ||
4104 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4105 "FOR"))
4106 COMPLETE_WITH("EACH", "ROW", "STATEMENT");
4107 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4108 "FOR", "EACH") ||
4109 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4110 "FOR", "EACH"))
4111 COMPLETE_WITH("ROW", "STATEMENT");
4112 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4113 "FOR", "EACH", "ROW|STATEMENT") ||
4114 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4115 "FOR", "EACH", "ROW|STATEMENT") ||
4116 Matches("CREATE", "TRIGGER", MatchAnyN,
4117 "FOR", "ROW|STATEMENT") ||
4118 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4119 "FOR", "ROW|STATEMENT"))
4120 {
4121 if (pset.sversion >= 110000)
4122 COMPLETE_WITH("WHEN (", "EXECUTE FUNCTION");
4123 else
4124 COMPLETE_WITH("WHEN (", "EXECUTE PROCEDURE");
4125 }
4126 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4127 "WHEN", "(*)") ||
4128 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4129 "WHEN", "(*)"))
4130 {
4131 if (pset.sversion >= 110000)
4132 COMPLETE_WITH("EXECUTE FUNCTION");
4133 else
4134 COMPLETE_WITH("EXECUTE PROCEDURE");
4135 }
4136
4137 /*
4138 * Complete CREATE [ OR REPLACE ] TRIGGER ... EXECUTE with
4139 * PROCEDURE|FUNCTION.
4140 */
4141 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4142 "EXECUTE") ||
4143 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4144 "EXECUTE"))
4145 {
4146 if (pset.sversion >= 110000)
4147 COMPLETE_WITH("FUNCTION");
4148 else
4149 COMPLETE_WITH("PROCEDURE");
4150 }
4151 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4152 "EXECUTE", "FUNCTION|PROCEDURE") ||
4153 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4154 "EXECUTE", "FUNCTION|PROCEDURE"))
4156
4157/* CREATE ROLE,USER,GROUP <name> */
4158 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny) &&
4159 !TailMatches("USER", "MAPPING"))
4160 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
4161 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
4162 "LOGIN", "NOBYPASSRLS",
4163 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
4164 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
4165 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
4166 "VALID UNTIL", "WITH");
4167
4168/* CREATE ROLE,USER,GROUP <name> WITH */
4169 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
4170 /* Similar to the above, but don't complete "WITH" again. */
4171 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
4172 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
4173 "LOGIN", "NOBYPASSRLS",
4174 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
4175 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
4176 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
4177 "VALID UNTIL");
4178
4179 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
4180 else if (Matches("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
4181 COMPLETE_WITH("GROUP", "ROLE");
4182
4183/* CREATE TYPE */
4184 else if (Matches("CREATE", "TYPE", MatchAny))
4185 COMPLETE_WITH("(", "AS");
4186 else if (Matches("CREATE", "TYPE", MatchAny, "AS"))
4187 COMPLETE_WITH("ENUM", "RANGE", "(");
4188 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "("))
4189 {
4190 if (TailMatches("(|*,", MatchAny))
4192 else if (TailMatches("(|*,", MatchAny, MatchAnyExcept("*)")))
4193 COMPLETE_WITH("COLLATE", ",", ")");
4194 }
4195 else if (Matches("CREATE", "TYPE", MatchAny, "AS", "ENUM|RANGE"))
4196 COMPLETE_WITH("(");
4197 else if (HeadMatches("CREATE", "TYPE", MatchAny, "("))
4198 {
4199 if (TailMatches("(|*,"))
4200 COMPLETE_WITH("INPUT", "OUTPUT", "RECEIVE", "SEND",
4201 "TYPMOD_IN", "TYPMOD_OUT", "ANALYZE", "SUBSCRIPT",
4202 "INTERNALLENGTH", "PASSEDBYVALUE", "ALIGNMENT",
4203 "STORAGE", "LIKE", "CATEGORY", "PREFERRED",
4204 "DEFAULT", "ELEMENT", "DELIMITER",
4205 "COLLATABLE");
4206 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
4207 COMPLETE_WITH("=");
4208 else if (TailMatches("=", MatchAnyExcept("*)")))
4209 COMPLETE_WITH(",", ")");
4210 }
4211 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "RANGE", "("))
4212 {
4213 if (TailMatches("(|*,"))
4214 COMPLETE_WITH("SUBTYPE", "SUBTYPE_OPCLASS", "COLLATION",
4215 "CANONICAL", "SUBTYPE_DIFF",
4216 "MULTIRANGE_TYPE_NAME");
4217 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
4218 COMPLETE_WITH("=");
4219 else if (TailMatches("=", MatchAnyExcept("*)")))
4220 COMPLETE_WITH(",", ")");
4221 }
4222
4223/* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
4224 /* Complete CREATE [ OR REPLACE ] VIEW <name> with AS or WITH */
4225 else if (TailMatches("CREATE", "VIEW", MatchAny) ||
4226 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny))
4227 COMPLETE_WITH("AS", "WITH");
4228 /* Complete "CREATE [ OR REPLACE ] VIEW <sth> AS with "SELECT" */
4229 else if (TailMatches("CREATE", "VIEW", MatchAny, "AS") ||
4230 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "AS"))
4231 COMPLETE_WITH("SELECT");
4232 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( yyy [= zzz] ) */
4233 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH") ||
4234 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH"))
4235 COMPLETE_WITH("(");
4236 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(") ||
4237 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "("))
4239 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option") ||
4240 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option"))
4241 COMPLETE_WITH("=");
4242 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option", "=") ||
4243 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option", "="))
4244 COMPLETE_WITH("local", "cascaded");
4245 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS */
4246 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)") ||
4247 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)"))
4248 COMPLETE_WITH("AS");
4249 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS SELECT */
4250 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)", "AS") ||
4251 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)", "AS"))
4252 COMPLETE_WITH("SELECT");
4253
4254/* CREATE MATERIALIZED VIEW */
4255 else if (Matches("CREATE", "MATERIALIZED"))
4256 COMPLETE_WITH("VIEW");
4257 /* Complete CREATE MATERIALIZED VIEW <name> with AS or USING */
4258 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
4259 COMPLETE_WITH("AS", "USING");
4260
4261 /*
4262 * Complete CREATE MATERIALIZED VIEW <name> USING with list of access
4263 * methods
4264 */
4265 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING"))
4267 /* Complete CREATE MATERIALIZED VIEW <name> USING <access method> with AS */
4268 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny))
4269 COMPLETE_WITH("AS");
4270
4271 /*
4272 * Complete CREATE MATERIALIZED VIEW <name> [USING <access method> ] AS
4273 * with "SELECT"
4274 */
4275 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS") ||
4276 Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS"))
4277 COMPLETE_WITH("SELECT");
4278
4279/* CREATE EVENT TRIGGER */
4280 else if (Matches("CREATE", "EVENT"))
4281 COMPLETE_WITH("TRIGGER");
4282 /* Complete CREATE EVENT TRIGGER <name> with ON */
4283 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny))
4284 COMPLETE_WITH("ON");
4285 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
4286 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
4287 COMPLETE_WITH("ddl_command_start", "ddl_command_end", "login",
4288 "sql_drop", "table_rewrite");
4289
4290 /*
4291 * Complete CREATE EVENT TRIGGER <name> ON <event_type>. EXECUTE FUNCTION
4292 * is the recommended grammar instead of EXECUTE PROCEDURE in version 11
4293 * and upwards.
4294 */
4295 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON", MatchAny))
4296 {
4297 if (pset.sversion >= 110000)
4298 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE FUNCTION");
4299 else
4300 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE PROCEDURE");
4301 }
4302 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "WHEN|AND", MatchAny, "IN", "(*)"))
4303 {
4304 if (pset.sversion >= 110000)
4305 COMPLETE_WITH("EXECUTE FUNCTION");
4306 else
4307 COMPLETE_WITH("EXECUTE PROCEDURE");
4308 }
4309 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "EXECUTE", "FUNCTION|PROCEDURE"))
4311
4312/* DEALLOCATE */
4313 else if (Matches("DEALLOCATE"))
4315 "ALL");
4316
4317/* DECLARE */
4318
4319 /*
4320 * Complete DECLARE <name> with one of BINARY, ASENSITIVE, INSENSITIVE,
4321 * SCROLL, NO SCROLL, and CURSOR.
4322 */
4323 else if (Matches("DECLARE", MatchAny))
4324 COMPLETE_WITH("BINARY", "ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL",
4325 "CURSOR");
4326
4327 /*
4328 * Complete DECLARE ... <option> with other options. The PostgreSQL parser
4329 * allows DECLARE options to be specified in any order. But the
4330 * tab-completion follows the ordering of them that the SQL standard
4331 * provides, like the syntax of DECLARE command in the documentation
4332 * indicates.
4333 */
4334 else if (Matches("DECLARE", MatchAnyN, "BINARY"))
4335 COMPLETE_WITH("ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR");
4336 else if (Matches("DECLARE", MatchAnyN, "ASENSITIVE|INSENSITIVE"))
4337 COMPLETE_WITH("SCROLL", "NO SCROLL", "CURSOR");
4338 else if (Matches("DECLARE", MatchAnyN, "SCROLL"))
4339 COMPLETE_WITH("CURSOR");
4340 /* Complete DECLARE ... [options] NO with SCROLL */
4341 else if (Matches("DECLARE", MatchAnyN, "NO"))
4342 COMPLETE_WITH("SCROLL");
4343
4344 /*
4345 * Complete DECLARE ... CURSOR with one of WITH HOLD, WITHOUT HOLD, and
4346 * FOR
4347 */
4348 else if (Matches("DECLARE", MatchAnyN, "CURSOR"))
4349 COMPLETE_WITH("WITH HOLD", "WITHOUT HOLD", "FOR");
4350 /* Complete DECLARE ... CURSOR WITH|WITHOUT with HOLD */
4351 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT"))
4352 COMPLETE_WITH("HOLD");
4353 /* Complete DECLARE ... CURSOR WITH|WITHOUT HOLD with FOR */
4354 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT", "HOLD"))
4355 COMPLETE_WITH("FOR");
4356
4357/* DELETE --- can be inside EXPLAIN, RULE, etc */
4358 /* Complete DELETE with "FROM" */
4359 else if (Matches("DELETE"))
4360 COMPLETE_WITH("FROM");
4361 /* Complete DELETE FROM with a list of tables */
4362 else if (TailMatches("DELETE", "FROM"))
4364 /* Complete DELETE FROM <table> */
4365 else if (TailMatches("DELETE", "FROM", MatchAny))
4366 COMPLETE_WITH("FOR", "USING", "WHERE");
4367 /* Complete DELETE FROM <table> FOR with PORTION */
4368 else if (TailMatches("DELETE", "FROM", MatchAny, "FOR"))
4369 COMPLETE_WITH("PORTION");
4370 /* Complete DELETE FROM <table> FOR PORTION with OF */
4371 else if (TailMatches("DELETE", "FROM", MatchAny, "FOR", "PORTION"))
4372 COMPLETE_WITH("OF");
4373 /* Complete DELETE FROM <table> FOR PORTION OF with column names */
4374 else if (TailMatches("DELETE", "FROM", MatchAny, "FOR", "PORTION", "OF"))
4376 /* Complete DELETE FROM <table> FOR PORTION OF <period> with FROM */
4377 else if (TailMatches("DELETE", "FROM", MatchAny, "FOR", "PORTION", "OF", MatchAny))
4378 COMPLETE_WITH("FROM");
4379 /* Complete DELETE FROM <table> USING with relations supporting SELECT */
4380 else if (TailMatches("DELETE", "FROM", MatchAny, "USING"))
4382
4383/* DISCARD */
4384 else if (Matches("DISCARD"))
4385 COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP");
4386
4387/* DO */
4388 else if (Matches("DO"))
4389 COMPLETE_WITH("LANGUAGE");
4390
4391/* DROP */
4392 /* Complete DROP object with CASCADE / RESTRICT */
4393 else if (Matches("DROP",
4394 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
4395 MatchAny) ||
4396 Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
4397 Matches("DROP", "EVENT", "TRIGGER", MatchAny) ||
4398 Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4399 Matches("DROP", "FOREIGN", "TABLE", MatchAny) ||
4400 Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
4401 COMPLETE_WITH("CASCADE", "RESTRICT");
4402 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
4403 ends_with(prev_wd, ')'))
4404 COMPLETE_WITH("CASCADE", "RESTRICT");
4405
4406 /* help completing some of the variants */
4407 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
4408 COMPLETE_WITH("(");
4409 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
4411 else if (Matches("DROP", "FOREIGN"))
4412 COMPLETE_WITH("DATA WRAPPER", "TABLE");
4413 else if (Matches("DROP", "DATABASE", MatchAny))
4414 COMPLETE_WITH("WITH (");
4415 else if (HeadMatches("DROP", "DATABASE") && (ends_with(prev_wd, '(')))
4416 COMPLETE_WITH("FORCE");
4417
4418 /* DROP INDEX */
4419 else if (Matches("DROP", "INDEX"))
4421 "CONCURRENTLY");
4422 else if (Matches("DROP", "INDEX", "CONCURRENTLY"))
4424 else if (Matches("DROP", "INDEX", MatchAny))
4425 COMPLETE_WITH("CASCADE", "RESTRICT");
4426 else if (Matches("DROP", "INDEX", "CONCURRENTLY", MatchAny))
4427 COMPLETE_WITH("CASCADE", "RESTRICT");
4428
4429 /* DROP MATERIALIZED VIEW */
4430 else if (Matches("DROP", "MATERIALIZED"))
4431 COMPLETE_WITH("VIEW");
4432 else if (Matches("DROP", "MATERIALIZED", "VIEW"))
4434 else if (Matches("DROP", "MATERIALIZED", "VIEW", MatchAny))
4435 COMPLETE_WITH("CASCADE", "RESTRICT");
4436
4437 /* DROP OWNED BY */
4438 else if (Matches("DROP", "OWNED"))
4439 COMPLETE_WITH("BY");
4440 else if (Matches("DROP", "OWNED", "BY"))
4442 else if (Matches("DROP", "OWNED", "BY", MatchAny))
4443 COMPLETE_WITH("CASCADE", "RESTRICT");
4444
4445 /* DROP TEXT SEARCH */
4446 else if (Matches("DROP", "TEXT", "SEARCH"))
4447 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
4448
4449 /* DROP TRIGGER */
4450 else if (Matches("DROP", "TRIGGER", MatchAny))
4451 COMPLETE_WITH("ON");
4452 else if (Matches("DROP", "TRIGGER", MatchAny, "ON"))
4453 {
4456 }
4457 else if (Matches("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
4458 COMPLETE_WITH("CASCADE", "RESTRICT");
4459
4460 /* DROP ACCESS METHOD */
4461 else if (Matches("DROP", "ACCESS"))
4462 COMPLETE_WITH("METHOD");
4463 else if (Matches("DROP", "ACCESS", "METHOD"))
4465
4466 /* DROP EVENT TRIGGER */
4467 else if (Matches("DROP", "EVENT"))
4468 COMPLETE_WITH("TRIGGER");
4469 else if (Matches("DROP", "EVENT", "TRIGGER"))
4471
4472 /* DROP POLICY <name> */
4473 else if (Matches("DROP", "POLICY"))
4475 /* DROP POLICY <name> ON */
4476 else if (Matches("DROP", "POLICY", MatchAny))
4477 COMPLETE_WITH("ON");
4478 /* DROP POLICY <name> ON <table> */
4479 else if (Matches("DROP", "POLICY", MatchAny, "ON"))
4480 {
4483 }
4484 else if (Matches("DROP", "POLICY", MatchAny, "ON", MatchAny))
4485 COMPLETE_WITH("CASCADE", "RESTRICT");
4486
4487 /* DROP PROPERTY GRAPH */
4488 else if (Matches("DROP", "PROPERTY"))
4489 COMPLETE_WITH("GRAPH");
4490 else if (Matches("DROP", "PROPERTY", "GRAPH"))
4492
4493 /* DROP RULE */
4494 else if (Matches("DROP", "RULE", MatchAny))
4495 COMPLETE_WITH("ON");
4496 else if (Matches("DROP", "RULE", MatchAny, "ON"))
4497 {
4500 }
4501 else if (Matches("DROP", "RULE", MatchAny, "ON", MatchAny))
4502 COMPLETE_WITH("CASCADE", "RESTRICT");
4503
4504 /* DROP TRANSFORM */
4505 else if (Matches("DROP", "TRANSFORM"))
4506 COMPLETE_WITH("FOR");
4507 else if (Matches("DROP", "TRANSFORM", "FOR"))
4509 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny))
4510 COMPLETE_WITH("LANGUAGE");
4511 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
4512 {
4515 }
4516 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE", MatchAny))
4517 COMPLETE_WITH("CASCADE", "RESTRICT");
4518
4519/* EXECUTE */
4520 else if (Matches("EXECUTE"))
4522
4523/*
4524 * EXPLAIN [ ( option [, ...] ) ] statement
4525 * EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
4526 */
4527 else if (Matches("EXPLAIN"))
4528 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4529 "MERGE INTO", "EXECUTE", "ANALYZE", "VERBOSE");
4530 else if (HeadMatches("EXPLAIN", "(*") &&
4531 !HeadMatches("EXPLAIN", "(*)"))
4532 {
4533 /*
4534 * This fires if we're in an unfinished parenthesized option list.
4535 * get_previous_words treats a completed parenthesized option list as
4536 * one word, so the above test is correct.
4537 */
4538 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
4539 COMPLETE_WITH("ANALYZE", "VERBOSE", "COSTS", "SETTINGS", "GENERIC_PLAN",
4540 "BUFFERS", "SERIALIZE", "WAL", "TIMING", "SUMMARY",
4541 "MEMORY", "FORMAT");
4542 else if (TailMatches("ANALYZE|VERBOSE|COSTS|SETTINGS|GENERIC_PLAN|BUFFERS|WAL|TIMING|SUMMARY|MEMORY"))
4543 COMPLETE_WITH("ON", "OFF");
4544 else if (TailMatches("SERIALIZE"))
4545 COMPLETE_WITH("TEXT", "NONE", "BINARY");
4546 else if (TailMatches("FORMAT"))
4547 COMPLETE_WITH("TEXT", "XML", "JSON", "YAML");
4548 }
4549 else if (Matches("EXPLAIN", "ANALYZE"))
4550 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4551 "MERGE INTO", "EXECUTE", "VERBOSE");
4552 else if (Matches("EXPLAIN", "(*)") ||
4553 Matches("EXPLAIN", "VERBOSE") ||
4554 Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
4555 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4556 "MERGE INTO", "EXECUTE");
4557
4558/* FETCH && MOVE */
4559
4560 /*
4561 * Complete FETCH with one of ABSOLUTE, BACKWARD, FORWARD, RELATIVE, ALL,
4562 * NEXT, PRIOR, FIRST, LAST, FROM, IN, and a list of cursors
4563 */
4564 else if (Matches("FETCH|MOVE"))
4566 "ABSOLUTE",
4567 "BACKWARD",
4568 "FORWARD",
4569 "RELATIVE",
4570 "ALL",
4571 "NEXT",
4572 "PRIOR",
4573 "FIRST",
4574 "LAST",
4575 "FROM",
4576 "IN");
4577
4578 /*
4579 * Complete FETCH BACKWARD or FORWARD with one of ALL, FROM, IN, and a
4580 * list of cursors
4581 */
4582 else if (Matches("FETCH|MOVE", "BACKWARD|FORWARD"))
4584 "ALL",
4585 "FROM",
4586 "IN");
4587
4588 /*
4589 * Complete FETCH <direction> with "FROM" or "IN". These are equivalent,
4590 * but we may as well tab-complete both: perhaps some users prefer one
4591 * variant or the other.
4592 */
4593 else if (Matches("FETCH|MOVE", "ABSOLUTE|BACKWARD|FORWARD|RELATIVE",
4594 MatchAnyExcept("FROM|IN")) ||
4595 Matches("FETCH|MOVE", "ALL|NEXT|PRIOR|FIRST|LAST"))
4597 "FROM",
4598 "IN");
4599 /* Complete FETCH <direction> "FROM" or "IN" with a list of cursors */
4600 else if (Matches("FETCH|MOVE", MatchAnyN, "FROM|IN"))
4602
4603/* FOREIGN DATA WRAPPER */
4604 /* applies in ALTER/DROP FDW and in CREATE SERVER */
4605 else if (TailMatches("FOREIGN", "DATA", "WRAPPER") &&
4606 !TailMatches("CREATE", MatchAny, MatchAny, MatchAny))
4608 /* applies in CREATE SERVER */
4609 else if (Matches("CREATE", "SERVER", MatchAnyN, "FOREIGN", "DATA", "WRAPPER", MatchAny))
4610 COMPLETE_WITH("OPTIONS");
4611
4612/* FOREIGN TABLE */
4613 else if (TailMatches("FOREIGN", "TABLE") &&
4614 !TailMatches("CREATE", MatchAny, MatchAny))
4616
4617/* FOREIGN SERVER */
4618 else if (TailMatches("FOREIGN", "SERVER"))
4620
4621/*
4622 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
4623 * ALTER DEFAULT PRIVILEGES, so use TailMatches
4624 */
4625 /* Complete GRANT/REVOKE with a list of roles and privileges */
4626 else if (TailMatches("GRANT|REVOKE") ||
4627 TailMatches("REVOKE", "ADMIN|GRANT|INHERIT|SET", "OPTION", "FOR"))
4628 {
4629 /*
4630 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
4631 * privileges (can't grant roles)
4632 */
4633 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4634 {
4635 if (TailMatches("GRANT") ||
4636 TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4637 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4638 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4639 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL");
4640 else if (TailMatches("REVOKE"))
4641 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4642 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4643 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL",
4644 "GRANT OPTION FOR");
4645 }
4646 else if (TailMatches("GRANT"))
4649 else if (TailMatches("REVOKE"))
4652 "GRANT OPTION FOR",
4653 "ADMIN OPTION FOR",
4654 "INHERIT OPTION FOR",
4655 "SET OPTION FOR");
4656 else if (TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4658 else if (TailMatches("REVOKE", "ADMIN|INHERIT|SET", "OPTION", "FOR"))
4660 }
4661
4662 else if (TailMatches("GRANT|REVOKE", "ALTER") ||
4663 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER"))
4664 COMPLETE_WITH("SYSTEM");
4665
4666 else if (TailMatches("REVOKE", "SET"))
4667 COMPLETE_WITH("ON PARAMETER", "OPTION FOR");
4668 else if (TailMatches("GRANT", "SET") ||
4669 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "SET") ||
4670 TailMatches("GRANT|REVOKE", "ALTER", "SYSTEM") ||
4671 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER", "SYSTEM"))
4672 COMPLETE_WITH("ON PARAMETER");
4673
4674 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "PARAMETER") ||
4675 TailMatches("GRANT|REVOKE", MatchAny, MatchAny, "ON", "PARAMETER") ||
4676 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER") ||
4677 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER"))
4679
4680 else if (TailMatches("GRANT", MatchAny, "ON", "PARAMETER", MatchAny) ||
4681 TailMatches("GRANT", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4682 COMPLETE_WITH("TO");
4683
4684 else if (TailMatches("REVOKE", MatchAny, "ON", "PARAMETER", MatchAny) ||
4685 TailMatches("REVOKE", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny) ||
4686 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER", MatchAny) ||
4687 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4688 COMPLETE_WITH("FROM");
4689
4690 /*
4691 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
4692 * TO/FROM
4693 */
4694 else if (TailMatches("GRANT|REVOKE", MatchAny) ||
4695 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny))
4696 {
4697 if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|MAINTAIN|ALL"))
4698 COMPLETE_WITH("ON");
4699 else if (TailMatches("GRANT", MatchAny))
4700 COMPLETE_WITH("TO");
4701 else
4702 COMPLETE_WITH("FROM");
4703 }
4704
4705 /*
4706 * Complete GRANT/REVOKE <sth> ON with a list of appropriate relations.
4707 *
4708 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
4709 * here will only work if the privilege list contains exactly one
4710 * privilege.
4711 */
4712 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON") ||
4713 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON"))
4714 {
4715 /*
4716 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
4717 * objects supported.
4718 */
4719 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4720 COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS", "LARGE OBJECTS");
4721 else
4723 "ALL FUNCTIONS IN SCHEMA",
4724 "ALL PROCEDURES IN SCHEMA",
4725 "ALL ROUTINES IN SCHEMA",
4726 "ALL SEQUENCES IN SCHEMA",
4727 "ALL TABLES IN SCHEMA",
4728 "DATABASE",
4729 "DOMAIN",
4730 "FOREIGN DATA WRAPPER",
4731 "FOREIGN SERVER",
4732 "FUNCTION",
4733 "LANGUAGE",
4734 "LARGE OBJECT",
4735 "PARAMETER",
4736 "PROCEDURE",
4737 "PROPERTY GRAPH",
4738 "ROUTINE",
4739 "SCHEMA",
4740 "SEQUENCE",
4741 "TABLE",
4742 "TABLESPACE",
4743 "TYPE");
4744 }
4745 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
4746 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
4747 COMPLETE_WITH("FUNCTIONS IN SCHEMA",
4748 "PROCEDURES IN SCHEMA",
4749 "ROUTINES IN SCHEMA",
4750 "SEQUENCES IN SCHEMA",
4751 "TABLES IN SCHEMA");
4752
4753 /*
4754 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
4755 * appropriate objects or keywords.
4756 *
4757 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
4758 */
4759 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny) ||
4760 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny))
4761 {
4762 if (TailMatches("DATABASE"))
4764 else if (TailMatches("DOMAIN"))
4766 else if (TailMatches("FUNCTION"))
4768 else if (TailMatches("FOREIGN"))
4769 COMPLETE_WITH("DATA WRAPPER", "SERVER");
4770 else if (TailMatches("LANGUAGE"))
4772 else if (TailMatches("LARGE"))
4773 {
4774 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4775 COMPLETE_WITH("OBJECTS");
4776 else
4777 COMPLETE_WITH("OBJECT");
4778 }
4779 else if (TailMatches("PROCEDURE"))
4781 else if (TailMatches("ROUTINE"))
4783 else if (TailMatches("SCHEMA"))
4785 else if (TailMatches("SEQUENCE"))
4787 else if (TailMatches("TABLE"))
4789 else if (TailMatches("TABLESPACE"))
4791 else if (TailMatches("TYPE"))
4793 else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
4794 COMPLETE_WITH("TO");
4795 else
4796 COMPLETE_WITH("FROM");
4797 }
4798
4799 /*
4800 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
4801 * CURRENT_ROLE, CURRENT_USER, or SESSION_USER.
4802 */
4803 else if (Matches("GRANT", MatchAnyN, "TO") ||
4804 Matches("REVOKE", MatchAnyN, "FROM"))
4807
4808 /*
4809 * Offer grant options after that.
4810 */
4811 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny))
4812 COMPLETE_WITH("WITH ADMIN",
4813 "WITH INHERIT",
4814 "WITH SET",
4815 "WITH GRANT OPTION",
4816 "GRANTED BY");
4817 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH"))
4818 COMPLETE_WITH("ADMIN",
4819 "INHERIT",
4820 "SET",
4821 "GRANT OPTION");
4822 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", "ADMIN|INHERIT|SET"))
4823 COMPLETE_WITH("OPTION", "TRUE", "FALSE");
4824 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION"))
4825 COMPLETE_WITH("GRANTED BY");
4826 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY"))
4829 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
4830 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO|FROM"))
4833 /* Offer WITH GRANT OPTION after that */
4834 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO", MatchAny))
4835 COMPLETE_WITH("WITH GRANT OPTION");
4836 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
4837 else if (Matches("GRANT|REVOKE", MatchAnyN, "ON", MatchAny, MatchAny) &&
4838 !TailMatches("FOREIGN", "SERVER") && !TailMatches("LARGE", "OBJECT"))
4839 {
4840 if (Matches("GRANT", MatchAnyN, "ON", MatchAny, MatchAny))
4841 COMPLETE_WITH("TO");
4842 else
4843 COMPLETE_WITH("FROM");
4844 }
4845
4846 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
4847 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
4848 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
4849 {
4851 COMPLETE_WITH("TO");
4852 else
4853 COMPLETE_WITH("FROM");
4854 }
4855
4856 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
4857 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4858 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
4859 {
4861 COMPLETE_WITH("TO");
4862 else
4863 COMPLETE_WITH("FROM");
4864 }
4865
4866 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
4867 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
4868 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
4869 {
4871 COMPLETE_WITH("TO");
4872 else
4873 COMPLETE_WITH("FROM");
4874 }
4875
4876 /* Complete "GRANT/REVOKE * ON LARGE OBJECT *" with TO/FROM */
4877 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "LARGE", "OBJECT", MatchAny) ||
4878 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "LARGE", "OBJECT", MatchAny))
4879 {
4881 COMPLETE_WITH("TO");
4882 else
4883 COMPLETE_WITH("FROM");
4884 }
4885
4886 /* Complete "GRANT/REVOKE * ON LARGE OBJECTS" with TO/FROM */
4887 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "LARGE", "OBJECTS") ||
4888 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "LARGE", "OBJECTS"))
4889 {
4891 COMPLETE_WITH("TO");
4892 else
4893 COMPLETE_WITH("FROM");
4894 }
4895
4896/* GRAPH_TABLE */
4897 else if (TailMatches("GRAPH_TABLE"))
4898 COMPLETE_WITH("(");
4899 else if (TailMatches("GRAPH_TABLE", "("))
4901 else if (TailMatches("GRAPH_TABLE", "(", MatchAny))
4902 COMPLETE_WITH("MATCH");
4903
4904/* GROUP BY */
4905 else if (TailMatches("FROM", MatchAny, "GROUP"))
4906 COMPLETE_WITH("BY");
4907
4908/* IMPORT FOREIGN SCHEMA */
4909 else if (Matches("IMPORT"))
4910 COMPLETE_WITH("FOREIGN SCHEMA");
4911 else if (Matches("IMPORT", "FOREIGN"))
4912 COMPLETE_WITH("SCHEMA");
4913 else if (Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny))
4914 COMPLETE_WITH("EXCEPT (", "FROM SERVER", "LIMIT TO (");
4915 else if (TailMatches("LIMIT", "TO", "(*)") ||
4916 Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny, "EXCEPT", "(*)"))
4917 COMPLETE_WITH("FROM SERVER");
4918 else if (TailMatches("FROM", "SERVER", MatchAny))
4919 COMPLETE_WITH("INTO");
4920 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO"))
4922 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO", MatchAny))
4923 COMPLETE_WITH("OPTIONS (");
4924
4925/* INSERT --- can be inside EXPLAIN, RULE, etc */
4926 /* Complete NOT MATCHED THEN INSERT */
4927 else if (TailMatches("NOT", "MATCHED", "THEN", "INSERT"))
4928 COMPLETE_WITH("VALUES", "(");
4929 /* Complete INSERT with "INTO" */
4930 else if (TailMatches("INSERT"))
4931 COMPLETE_WITH("INTO");
4932 /* Complete INSERT INTO with table names */
4933 else if (TailMatches("INSERT", "INTO"))
4935 /* Complete "INSERT INTO <table> (" with attribute names */
4936 else if (TailMatches("INSERT", "INTO", MatchAny, "("))
4938
4939 /*
4940 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
4941 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
4942 */
4943 else if (TailMatches("INSERT", "INTO", MatchAny))
4944 COMPLETE_WITH("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
4945
4946 /*
4947 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
4948 * "TABLE" or "OVERRIDING"
4949 */
4950 else if (TailMatches("INSERT", "INTO", MatchAny, MatchAny) &&
4951 ends_with(prev_wd, ')'))
4952 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "OVERRIDING");
4953
4954 /* Complete OVERRIDING */
4955 else if (TailMatches("OVERRIDING"))
4956 COMPLETE_WITH("SYSTEM VALUE", "USER VALUE");
4957
4958 /* Complete after OVERRIDING clause */
4959 else if (TailMatches("OVERRIDING", MatchAny, "VALUE"))
4960 COMPLETE_WITH("SELECT", "TABLE", "VALUES");
4961
4962 /* Insert an open parenthesis after "VALUES" */
4963 else if (TailMatches("VALUES") && !TailMatches("DEFAULT", "VALUES"))
4964 COMPLETE_WITH("(");
4965
4966/* LOCK */
4967 /* Complete LOCK [TABLE] [ONLY] with a list of tables */
4968 else if (Matches("LOCK"))
4970 "TABLE", "ONLY");
4971 else if (Matches("LOCK", "TABLE"))
4973 "ONLY");
4974 else if (Matches("LOCK", "TABLE", "ONLY") || Matches("LOCK", "ONLY"))
4976 /* For the following, handle the case of a single table only for now */
4977
4978 /* Complete LOCK [TABLE] [ONLY] <table> with IN or NOWAIT */
4979 else if (Matches("LOCK", MatchAnyExcept("TABLE|ONLY")) ||
4980 Matches("LOCK", "TABLE", MatchAnyExcept("ONLY")) ||
4981 Matches("LOCK", "ONLY", MatchAny) ||
4982 Matches("LOCK", "TABLE", "ONLY", MatchAny))
4983 COMPLETE_WITH("IN", "NOWAIT");
4984
4985 /* Complete LOCK [TABLE] [ONLY] <table> IN with a lock mode */
4986 else if (Matches("LOCK", MatchAnyN, "IN"))
4987 COMPLETE_WITH("ACCESS SHARE MODE",
4988 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
4989 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
4990 "SHARE ROW EXCLUSIVE MODE",
4991 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
4992
4993 /*
4994 * Complete LOCK [TABLE][ONLY] <table> IN ACCESS|ROW with rest of lock
4995 * mode
4996 */
4997 else if (Matches("LOCK", MatchAnyN, "IN", "ACCESS|ROW"))
4998 COMPLETE_WITH("EXCLUSIVE MODE", "SHARE MODE");
4999
5000 /* Complete LOCK [TABLE] [ONLY] <table> IN SHARE with rest of lock mode */
5001 else if (Matches("LOCK", MatchAnyN, "IN", "SHARE"))
5002 COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE",
5003 "UPDATE EXCLUSIVE MODE");
5004
5005 /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with "NOWAIT" */
5006 else if (Matches("LOCK", MatchAnyN, "MODE"))
5007 COMPLETE_WITH("NOWAIT");
5008
5009/* MERGE --- can be inside EXPLAIN */
5010 else if (TailMatches("MERGE"))
5011 COMPLETE_WITH("INTO");
5012 else if (TailMatches("MERGE", "INTO"))
5014
5015 /* Complete MERGE INTO <table> [[AS] <alias>] with USING */
5016 else if (TailMatches("MERGE", "INTO", MatchAny))
5017 COMPLETE_WITH("USING", "AS");
5018 else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
5019 TailMatches("MERGE", "INTO", MatchAny, MatchAnyExcept("USING|AS")))
5020 COMPLETE_WITH("USING");
5021
5022 /*
5023 * Complete MERGE INTO ... USING with a list of relations supporting
5024 * SELECT
5025 */
5026 else if (TailMatches("MERGE", "INTO", MatchAny, "USING") ||
5027 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING") ||
5028 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING"))
5030
5031 /*
5032 * Complete MERGE INTO <table> [[AS] <alias>] USING <relations> [[AS]
5033 * alias] with ON
5034 */
5035 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny) ||
5036 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny) ||
5037 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny))
5038 COMPLETE_WITH("AS", "ON");
5039 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5040 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5041 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5042 TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
5043 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
5044 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")))
5045 COMPLETE_WITH("ON");
5046
5047 /* Complete MERGE INTO ... ON with target table attributes */
5048 else if (TailMatches("INTO", MatchAny, "USING", MatchAny, "ON"))
5050 else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny, "ON"))
5052 else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAny, "ON"))
5054
5055 /*
5056 * Complete ... USING <relation> [[AS] alias] ON join condition
5057 * (consisting of one or three words typically used) with WHEN [NOT]
5058 * MATCHED
5059 */
5060 else if (TailMatches("USING", MatchAny, "ON", MatchAny) ||
5061 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny) ||
5062 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny) ||
5063 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
5064 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
5065 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")))
5066 COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
5067 else if (TailMatches("USING", MatchAny, "ON", MatchAny, "WHEN") ||
5068 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, "WHEN") ||
5069 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, "WHEN") ||
5070 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
5071 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
5072 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN"))
5073 COMPLETE_WITH("MATCHED", "NOT MATCHED");
5074
5075 /*
5076 * Complete ... WHEN MATCHED and WHEN NOT MATCHED BY SOURCE|TARGET with
5077 * THEN/AND
5078 */
5079 else if (TailMatches("WHEN", "MATCHED") ||
5080 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE|TARGET"))
5081 COMPLETE_WITH("THEN", "AND");
5082
5083 /* Complete ... WHEN NOT MATCHED with BY/THEN/AND */
5084 else if (TailMatches("WHEN", "NOT", "MATCHED"))
5085 COMPLETE_WITH("BY", "THEN", "AND");
5086
5087 /* Complete ... WHEN NOT MATCHED BY with SOURCE/TARGET */
5088 else if (TailMatches("WHEN", "NOT", "MATCHED", "BY"))
5089 COMPLETE_WITH("SOURCE", "TARGET");
5090
5091 /*
5092 * Complete ... WHEN MATCHED THEN and WHEN NOT MATCHED BY SOURCE THEN with
5093 * UPDATE SET/DELETE/DO NOTHING
5094 */
5095 else if (TailMatches("WHEN", "MATCHED", "THEN") ||
5096 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE", "THEN"))
5097 COMPLETE_WITH("UPDATE SET", "DELETE", "DO NOTHING");
5098
5099 /*
5100 * Complete ... WHEN NOT MATCHED [BY TARGET] THEN with INSERT/DO NOTHING
5101 */
5102 else if (TailMatches("WHEN", "NOT", "MATCHED", "THEN") ||
5103 TailMatches("WHEN", "NOT", "MATCHED", "BY", "TARGET", "THEN"))
5104 COMPLETE_WITH("INSERT", "DO NOTHING");
5105
5106/* NOTIFY --- can be inside EXPLAIN, RULE, etc */
5107 else if (TailMatches("NOTIFY"))
5109
5110/* OPTIONS */
5111 else if (TailMatches("OPTIONS"))
5112 COMPLETE_WITH("(");
5113
5114/* OWNER TO - complete with available roles */
5115 else if (TailMatches("OWNER", "TO"))
5118
5119/* ORDER BY */
5120 else if (TailMatches("FROM", MatchAny, "ORDER"))
5121 COMPLETE_WITH("BY");
5122 else if (TailMatches("FROM", MatchAny, "ORDER", "BY"))
5124
5125/* PREPARE xx AS */
5126 else if (Matches("PREPARE", MatchAny, "AS"))
5127 COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM",
5128 "MERGE INTO", "VALUES", "WITH", "TABLE");
5129
5130/*
5131 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
5132 * managers, not for manual use in interactive sessions.
5133 */
5134
5135/* REASSIGN OWNED BY xxx TO yyy */
5136 else if (Matches("REASSIGN"))
5137 COMPLETE_WITH("OWNED BY");
5138 else if (Matches("REASSIGN", "OWNED"))
5139 COMPLETE_WITH("BY");
5140 else if (Matches("REASSIGN", "OWNED", "BY"))
5142 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny))
5143 COMPLETE_WITH("TO");
5144 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
5146
5147/* REFRESH MATERIALIZED VIEW */
5148 else if (Matches("REFRESH"))
5149 COMPLETE_WITH("MATERIALIZED VIEW");
5150 else if (Matches("REFRESH", "MATERIALIZED"))
5151 COMPLETE_WITH("VIEW");
5152 else if (Matches("REFRESH", "MATERIALIZED", "VIEW"))
5154 "CONCURRENTLY");
5155 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
5157 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
5158 COMPLETE_WITH("WITH");
5159 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
5160 COMPLETE_WITH("WITH");
5161 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
5162 COMPLETE_WITH("NO DATA", "DATA");
5163 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
5164 COMPLETE_WITH("NO DATA", "DATA");
5165 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
5166 COMPLETE_WITH("DATA");
5167 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
5168 COMPLETE_WITH("DATA");
5169
5170/* REINDEX */
5171 else if (Matches("REINDEX") ||
5172 Matches("REINDEX", "(*)"))
5173 COMPLETE_WITH("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
5174 else if (Matches("REINDEX", "TABLE") ||
5175 Matches("REINDEX", "(*)", "TABLE"))
5177 "CONCURRENTLY");
5178 else if (Matches("REINDEX", "INDEX") ||
5179 Matches("REINDEX", "(*)", "INDEX"))
5181 "CONCURRENTLY");
5182 else if (Matches("REINDEX", "SCHEMA") ||
5183 Matches("REINDEX", "(*)", "SCHEMA"))
5185 "CONCURRENTLY");
5186 else if (Matches("REINDEX", "SYSTEM|DATABASE") ||
5187 Matches("REINDEX", "(*)", "SYSTEM|DATABASE"))
5189 "CONCURRENTLY");
5190 else if (Matches("REINDEX", "TABLE", "CONCURRENTLY") ||
5191 Matches("REINDEX", "(*)", "TABLE", "CONCURRENTLY"))
5193 else if (Matches("REINDEX", "INDEX", "CONCURRENTLY") ||
5194 Matches("REINDEX", "(*)", "INDEX", "CONCURRENTLY"))
5196 else if (Matches("REINDEX", "SCHEMA", "CONCURRENTLY") ||
5197 Matches("REINDEX", "(*)", "SCHEMA", "CONCURRENTLY"))
5199 else if (Matches("REINDEX", "SYSTEM|DATABASE", "CONCURRENTLY") ||
5200 Matches("REINDEX", "(*)", "SYSTEM|DATABASE", "CONCURRENTLY"))
5202 else if (HeadMatches("REINDEX", "(*") &&
5203 !HeadMatches("REINDEX", "(*)"))
5204 {
5205 /*
5206 * This fires if we're in an unfinished parenthesized option list.
5207 * get_previous_words treats a completed parenthesized option list as
5208 * one word, so the above test is correct.
5209 */
5210 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5211 COMPLETE_WITH("CONCURRENTLY", "TABLESPACE", "VERBOSE");
5212 else if (TailMatches("TABLESPACE"))
5214 }
5215
5216/* REPACK */
5217 else if (Matches("REPACK"))
5219 "(", "USING INDEX");
5220 else if (Matches("REPACK", "(*)"))
5222 "USING INDEX");
5223 else if (Matches("REPACK", MatchAnyExcept("(")))
5224 COMPLETE_WITH("USING INDEX");
5225 else if (Matches("REPACK", "(*)", MatchAnyExcept("(")))
5226 COMPLETE_WITH("USING INDEX");
5227 else if (Matches("REPACK", MatchAny, "USING", "INDEX") ||
5228 Matches("REPACK", "(*)", MatchAny, "USING", "INDEX"))
5229 {
5232 }
5233
5234 /*
5235 * Complete ... [ (*) ] <sth> USING INDEX, with a list of indexes for
5236 * <sth>.
5237 */
5238 else if (TailMatches(MatchAny, "USING", "INDEX"))
5239 {
5242 }
5243 else if (HeadMatches("REPACK", "(*") &&
5244 !HeadMatches("REPACK", "(*)"))
5245 {
5246 /*
5247 * This fires if we're in an unfinished parenthesized option list.
5248 * get_previous_words treats a completed parenthesized option list as
5249 * one word, so the above test is correct.
5250 */
5251 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5252 COMPLETE_WITH("ANALYZE", "CONCURRENTLY", "VERBOSE");
5253 else if (TailMatches("ANALYZE", "CONCURRENTLY", "VERBOSE"))
5254 COMPLETE_WITH("ON", "OFF");
5255 }
5256
5257/* SECURITY LABEL */
5258 else if (Matches("SECURITY"))
5259 COMPLETE_WITH("LABEL");
5260 else if (Matches("SECURITY", "LABEL"))
5261 COMPLETE_WITH("ON", "FOR");
5262 else if (Matches("SECURITY", "LABEL", "FOR", MatchAny))
5263 COMPLETE_WITH("ON");
5264 else if (Matches("SECURITY", "LABEL", "ON") ||
5265 Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
5266 COMPLETE_WITH("TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
5267 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION",
5268 "LARGE OBJECT", "MATERIALIZED VIEW", "LANGUAGE",
5269 "PROPERTY GRAPH", "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
5270 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW");
5271 else if (Matches("SECURITY", "LABEL", "ON", "PROPERTY", "GRAPH"))
5273 else if (Matches("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
5274 COMPLETE_WITH("IS");
5275
5276/* SELECT */
5277 /* naah . . . */
5278
5279/* SET, RESET, SHOW */
5280 /* Complete with a variable name */
5281 else if (TailMatches("SET|RESET") &&
5282 !TailMatches("UPDATE", MatchAny, "SET") &&
5283 !TailMatches("ALTER", "DATABASE|USER|ROLE", MatchAny, "RESET"))
5285 "CONSTRAINTS",
5286 "TRANSACTION",
5287 "SESSION",
5288 "ROLE",
5289 "TABLESPACE",
5290 "ALL");
5291 else if (Matches("SHOW"))
5293 "SESSION AUTHORIZATION",
5294 "ALL");
5295 else if (Matches("SHOW", "SESSION"))
5296 COMPLETE_WITH("AUTHORIZATION");
5297 /* Complete "SET TRANSACTION" */
5298 else if (Matches("SET", "TRANSACTION"))
5299 COMPLETE_WITH("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
5300 else if (Matches("BEGIN|START", "TRANSACTION") ||
5301 Matches("BEGIN", "WORK") ||
5302 Matches("BEGIN") ||
5303 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
5304 COMPLETE_WITH("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
5305 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
5306 Matches("BEGIN", "NOT") ||
5307 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
5308 COMPLETE_WITH("DEFERRABLE");
5309 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
5310 Matches("BEGIN", "ISOLATION") ||
5311 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
5312 COMPLETE_WITH("LEVEL");
5313 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
5314 Matches("BEGIN", "ISOLATION", "LEVEL") ||
5315 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
5316 COMPLETE_WITH("READ", "REPEATABLE READ", "SERIALIZABLE");
5317 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
5318 Matches("BEGIN", "ISOLATION", "LEVEL", "READ") ||
5319 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
5320 COMPLETE_WITH("UNCOMMITTED", "COMMITTED");
5321 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
5322 Matches("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
5323 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
5324 COMPLETE_WITH("READ");
5325 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
5326 Matches("BEGIN", "READ") ||
5327 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
5328 COMPLETE_WITH("ONLY", "WRITE");
5329 /* SET CONSTRAINTS */
5330 else if (Matches("SET", "CONSTRAINTS"))
5332 "ALL");
5333 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
5334 else if (Matches("SET", "CONSTRAINTS", MatchAny))
5335 COMPLETE_WITH("DEFERRED", "IMMEDIATE");
5336 /* Complete SET ROLE */
5337 else if (Matches("SET", "ROLE"))
5339 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
5340 else if (Matches("SET", "SESSION"))
5341 COMPLETE_WITH("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
5342 /* Complete SET SESSION AUTHORIZATION with username */
5343 else if (Matches("SET", "SESSION", "AUTHORIZATION"))
5345 "DEFAULT");
5346 /* Complete RESET SESSION with AUTHORIZATION */
5347 else if (Matches("RESET", "SESSION"))
5348 COMPLETE_WITH("AUTHORIZATION");
5349 /* Complete SET <var> with "TO" */
5350 else if (Matches("SET", MatchAny))
5351 COMPLETE_WITH("TO");
5352
5353 /*
5354 * Complete ALTER DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER ... SET
5355 * <name>
5356 */
5357 else if (Matches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER", MatchAnyN, "SET", MatchAnyExcept("SCHEMA")))
5358 COMPLETE_WITH("FROM CURRENT", "TO");
5359
5360 /*
5361 * Suggest possible variable values in SET variable TO|=, along with the
5362 * preceding ALTER syntaxes.
5363 */
5364 else if (TailMatches("SET", MatchAny, "TO|=") &&
5365 !TailMatches("UPDATE", MatchAny, "SET", MatchAny, "TO|="))
5366 {
5367 /* special cased code for individual GUCs */
5368 if (TailMatches("DateStyle", "TO|="))
5369 COMPLETE_WITH("ISO", "SQL", "Postgres", "German",
5370 "YMD", "DMY", "MDY",
5371 "US", "European", "NonEuropean",
5372 "DEFAULT");
5373 else if (TailMatches("search_path", "TO|="))
5374 {
5375 /* Here, we want to allow pg_catalog, so use narrower exclusion */
5377 " AND nspname NOT LIKE E'pg\\\\_toast%%'"
5378 " AND nspname NOT LIKE E'pg\\\\_temp%%'",
5379 "DEFAULT");
5380 }
5381 else if (TailMatches("TimeZone", "TO|="))
5383 else
5384 {
5385 /* generic, type based, GUC support */
5386 char *guctype = get_guctype(prev2_wd);
5387
5388 /*
5389 * Note: if we don't recognize the GUC name, it's important to not
5390 * offer any completions, as most likely we've misinterpreted the
5391 * context and this isn't a GUC-setting command at all.
5392 */
5393 if (guctype)
5394 {
5395 if (strcmp(guctype, "enum") == 0)
5396 {
5399 "DEFAULT");
5400 }
5401 else if (strcmp(guctype, "bool") == 0)
5402 COMPLETE_WITH("on", "off", "true", "false", "yes", "no",
5403 "1", "0", "DEFAULT");
5404 else
5405 COMPLETE_WITH("DEFAULT");
5406
5407 free(guctype);
5408 }
5409 }
5410 }
5411
5412/* START TRANSACTION */
5413 else if (Matches("START"))
5414 COMPLETE_WITH("TRANSACTION");
5415
5416/* TABLE, but not TABLE embedded in other commands */
5417 else if (Matches("TABLE"))
5419
5420/* TABLESAMPLE */
5421 else if (TailMatches("TABLESAMPLE"))
5423 else if (TailMatches("TABLESAMPLE", MatchAny))
5424 COMPLETE_WITH("(");
5425
5426/* TRUNCATE */
5427 else if (Matches("TRUNCATE"))
5429 "TABLE", "ONLY");
5430 else if (Matches("TRUNCATE", "TABLE"))
5432 "ONLY");
5433 else if (Matches("TRUNCATE", MatchAnyN, "ONLY"))
5435 else if (Matches("TRUNCATE", MatchAny) ||
5436 Matches("TRUNCATE", "TABLE|ONLY", MatchAny) ||
5437 Matches("TRUNCATE", "TABLE", "ONLY", MatchAny))
5438 COMPLETE_WITH("RESTART IDENTITY", "CONTINUE IDENTITY", "CASCADE", "RESTRICT");
5439 else if (Matches("TRUNCATE", MatchAnyN, "IDENTITY"))
5440 COMPLETE_WITH("CASCADE", "RESTRICT");
5441
5442/* UNLISTEN */
5443 else if (Matches("UNLISTEN"))
5445
5446/* UPDATE --- can be inside EXPLAIN, RULE, etc */
5447 /* If prev. word is UPDATE suggest a list of tables */
5448 else if (TailMatches("UPDATE"))
5450 /* Complete UPDATE <table> with "SET" or "FOR" (for FOR PORTION OF) */
5451 else if (TailMatches("UPDATE", MatchAny))
5452 COMPLETE_WITH("FOR", "SET");
5453 /* Complete UPDATE <table> FOR with PORTION */
5454 else if (TailMatches("UPDATE", MatchAny, "FOR"))
5455 COMPLETE_WITH("PORTION");
5456 /* Complete UPDATE <table> FOR PORTION with OF */
5457 else if (TailMatches("UPDATE", MatchAny, "FOR", "PORTION"))
5458 COMPLETE_WITH("OF");
5459 /* Complete UPDATE <table> FOR PORTION OF with column names */
5460 else if (TailMatches("UPDATE", MatchAny, "FOR", "PORTION", "OF"))
5462 /* Complete UPDATE <table> FOR PORTION OF <period> with FROM */
5463 else if (TailMatches("UPDATE", MatchAny, "FOR", "PORTION", "OF", MatchAny))
5464 COMPLETE_WITH("FROM");
5465 /* Complete UPDATE <table> SET with list of attributes */
5466 else if (TailMatches("UPDATE", MatchAny, "SET"))
5468 /* UPDATE <table> SET <attr> = */
5469 else if (TailMatches("UPDATE", MatchAny, "SET", MatchAnyExcept("*=")))
5470 COMPLETE_WITH("=");
5471
5472/* USER MAPPING */
5473 else if (Matches("ALTER|CREATE|DROP", "USER", "MAPPING"))
5474 COMPLETE_WITH("FOR");
5475 else if (Matches("CREATE", "USER", "MAPPING", "FOR"))
5477 "CURRENT_ROLE",
5478 "CURRENT_USER",
5479 "PUBLIC",
5480 "USER");
5481 else if (Matches("ALTER|DROP", "USER", "MAPPING", "FOR"))
5483 else if (Matches("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
5484 COMPLETE_WITH("SERVER");
5485 else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
5486 COMPLETE_WITH("OPTIONS");
5487
5488/*
5489 * VACUUM [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
5490 * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ [ ONLY ] table_and_columns [, ...] ]
5491 */
5492 else if (Matches("VACUUM"))
5494 "(",
5495 "FULL",
5496 "FREEZE",
5497 "VERBOSE",
5498 "ANALYZE",
5499 "ONLY");
5500 else if (HeadMatches("VACUUM", "(*") &&
5501 !HeadMatches("VACUUM", "(*)"))
5502 {
5503 /*
5504 * This fires if we're in an unfinished parenthesized option list.
5505 * get_previous_words treats a completed parenthesized option list as
5506 * one word, so the above test is correct.
5507 */
5508 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5509 COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
5510 "DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
5511 "INDEX_CLEANUP", "PROCESS_MAIN", "PROCESS_TOAST",
5512 "TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
5513 "ONLY_DATABASE_STATS", "BUFFER_USAGE_LIMIT");
5514 else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_MAIN|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
5515 COMPLETE_WITH("ON", "OFF");
5516 else if (TailMatches("INDEX_CLEANUP"))
5517 COMPLETE_WITH("AUTO", "ON", "OFF");
5518 }
5519 else if (Matches("VACUUM", "(*)"))
5521 "ONLY");
5522 else if (Matches("VACUUM", "FULL"))
5524 "FREEZE",
5525 "VERBOSE",
5526 "ANALYZE",
5527 "ONLY");
5528 else if (Matches("VACUUM", MatchAnyN, "FREEZE"))
5530 "VERBOSE",
5531 "ANALYZE",
5532 "ONLY");
5533 else if (Matches("VACUUM", MatchAnyN, "VERBOSE"))
5535 "ANALYZE",
5536 "ONLY");
5537 else if (Matches("VACUUM", MatchAnyN, "ANALYZE"))
5539 "ONLY");
5540 else if (Matches("VACUUM", MatchAnyN, "("))
5541 /* "VACUUM (" should be caught above, so assume we want columns */
5543 else if (HeadMatches("VACUUM"))
5545
5546/*
5547 * WAIT FOR LSN '<lsn>' [ WITH ( option [, ...] ) ]
5548 * where option can be:
5549 * MODE '<mode>'
5550 * TIMEOUT '<timeout>'
5551 * NO_THROW
5552 * and mode can be:
5553 * standby_replay | standby_write | standby_flush | primary_flush
5554 */
5555 else if (Matches("WAIT"))
5556 COMPLETE_WITH("FOR");
5557 else if (Matches("WAIT", "FOR"))
5558 COMPLETE_WITH("LSN");
5559 else if (Matches("WAIT", "FOR", "LSN"))
5560 /* No completion for LSN value - user must provide manually */
5561 ;
5562 else if (Matches("WAIT", "FOR", "LSN", MatchAny))
5563 COMPLETE_WITH("WITH");
5564 else if (Matches("WAIT", "FOR", "LSN", MatchAny, "WITH"))
5565 COMPLETE_WITH("(");
5566
5567 /*
5568 * Handle parenthesized option list. This fires when we're in an
5569 * unfinished parenthesized option list. get_previous_words treats a
5570 * completed parenthesized option list as one word, so the above test is
5571 * correct.
5572 *
5573 * 'mode' takes a string value (one of the listed above), 'timeout' takes
5574 * a string value, and 'no_throw' takes no value. We do not offer
5575 * completions for the *values* of 'timeout' or 'no_throw'.
5576 */
5577 else if (HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*") &&
5578 !HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*)"))
5579 {
5580 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5581 COMPLETE_WITH("mode", "timeout", "no_throw");
5582 else if (TailMatches("mode"))
5583 COMPLETE_WITH("'standby_replay'", "'standby_write'", "'standby_flush'", "'primary_flush'");
5584 }
5585
5586/* WITH [RECURSIVE] */
5587
5588 /*
5589 * Only match when WITH is the first word, as WITH may appear in many
5590 * other contexts.
5591 */
5592 else if (Matches("WITH"))
5593 COMPLETE_WITH("RECURSIVE");
5594
5595/* WHERE */
5596 /* Simple case of the word before the where being the table name */
5597 else if (TailMatches(MatchAny, "WHERE"))
5599
5600/* ... FROM ... */
5601/* TODO: also include SRF ? */
5602 else if (TailMatches("FROM") && !Matches("COPY|\\copy", MatchAny, "FROM"))
5604
5605/* ... JOIN ... */
5606 else if (TailMatches("JOIN"))
5608 else if (TailMatches("JOIN", MatchAny) && !TailMatches("CROSS|NATURAL", "JOIN", MatchAny))
5609 COMPLETE_WITH("ON", "USING (");
5610 else if (TailMatches("JOIN", MatchAny, MatchAny) &&
5611 !TailMatches("CROSS|NATURAL", "JOIN", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5612 COMPLETE_WITH("ON", "USING (");
5613 else if (TailMatches("JOIN", "LATERAL", MatchAny, MatchAny) &&
5614 !TailMatches("CROSS|NATURAL", "JOIN", "LATERAL", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5615 COMPLETE_WITH("ON", "USING (");
5616 else if (TailMatches("JOIN", MatchAny, "USING") ||
5617 TailMatches("JOIN", MatchAny, MatchAny, "USING") ||
5618 TailMatches("JOIN", "LATERAL", MatchAny, MatchAny, "USING"))
5619 COMPLETE_WITH("(");
5620 else if (TailMatches("JOIN", MatchAny, "USING", "("))
5622 else if (TailMatches("JOIN", MatchAny, MatchAny, "USING", "("))
5624
5625/* ... AT [ LOCAL | TIME ZONE ] ... */
5626 else if (TailMatches("AT"))
5627 COMPLETE_WITH("LOCAL", "TIME ZONE");
5628 else if (TailMatches("AT", "TIME", "ZONE"))
5630
5631/* Backslash commands */
5632/* TODO: \dc \dd \dl */
5633 else if (TailMatchesCS("\\?"))
5634 COMPLETE_WITH_CS("commands", "options", "variables");
5635 else if (TailMatchesCS("\\connect|\\c"))
5636 {
5639 }
5640 else if (TailMatchesCS("\\connect|\\c", MatchAny))
5641 {
5644 }
5645 else if (TailMatchesCS("\\da*"))
5647 else if (TailMatchesCS("\\dAc*", MatchAny) ||
5648 TailMatchesCS("\\dAf*", MatchAny))
5650 else if (TailMatchesCS("\\dAo*", MatchAny) ||
5651 TailMatchesCS("\\dAp*", MatchAny))
5653 else if (TailMatchesCS("\\dA*"))
5655 else if (TailMatchesCS("\\db*"))
5657 else if (TailMatchesCS("\\dconfig*"))
5659 else if (TailMatchesCS("\\dD*"))
5661 else if (TailMatchesCS("\\des*"))
5663 else if (TailMatchesCS("\\deu*"))
5665 else if (TailMatchesCS("\\dew*"))
5667 else if (TailMatchesCS("\\df*"))
5669 else if (HeadMatchesCS("\\df*"))
5671
5672 else if (TailMatchesCS("\\dFd*"))
5674 else if (TailMatchesCS("\\dFp*"))
5676 else if (TailMatchesCS("\\dFt*"))
5678 /* must be at end of \dF alternatives: */
5679 else if (TailMatchesCS("\\dF*"))
5681
5682 else if (TailMatchesCS("\\di*"))
5684 else if (TailMatchesCS("\\dL*"))
5686 else if (TailMatchesCS("\\dn*"))
5688 /* no support for completing operators, but we can complete types: */
5689 else if (HeadMatchesCS("\\do*", MatchAny))
5691 else if (TailMatchesCS("\\dp") || TailMatchesCS("\\z"))
5693 else if (TailMatchesCS("\\dPi*"))
5695 else if (TailMatchesCS("\\dPt*"))
5697 else if (TailMatchesCS("\\dP*"))
5699 else if (TailMatchesCS("\\dRp*"))
5701 else if (TailMatchesCS("\\dRs*"))
5703 else if (TailMatchesCS("\\ds*"))
5705 else if (TailMatchesCS("\\dt*"))
5707 else if (TailMatchesCS("\\dT*"))
5709 else if (TailMatchesCS("\\du*") ||
5710 TailMatchesCS("\\dg*") ||
5711 TailMatchesCS("\\drg*"))
5713 else if (TailMatchesCS("\\dv*"))
5715 else if (TailMatchesCS("\\dx*"))
5717 else if (TailMatchesCS("\\dX*"))
5719 else if (TailMatchesCS("\\dm*"))
5721 else if (TailMatchesCS("\\dE*"))
5723 else if (TailMatchesCS("\\dy*"))
5725
5726 /* must be at end of \d alternatives: */
5727 else if (TailMatchesCS("\\d*"))
5729
5730 else if (TailMatchesCS("\\ef"))
5732 else if (TailMatchesCS("\\ev"))
5734
5735 else if (TailMatchesCS("\\encoding"))
5737 else if (TailMatchesCS("\\h|\\help"))
5739 else if (TailMatchesCS("\\h|\\help", MatchAny))
5740 {
5741 if (TailMatches("DROP"))
5743 else if (TailMatches("ALTER"))
5745
5746 /*
5747 * CREATE is recognized by tail match elsewhere, so doesn't need to be
5748 * repeated here
5749 */
5750 }
5751 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny))
5752 {
5753 if (TailMatches("CREATE|DROP", "ACCESS"))
5754 COMPLETE_WITH("METHOD");
5755 else if (TailMatches("ALTER", "DEFAULT"))
5756 COMPLETE_WITH("PRIVILEGES");
5757 else if (TailMatches("CREATE|ALTER|DROP", "EVENT"))
5758 COMPLETE_WITH("TRIGGER");
5759 else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN"))
5760 COMPLETE_WITH("DATA WRAPPER", "TABLE");
5761 else if (TailMatches("ALTER", "LARGE"))
5762 COMPLETE_WITH("OBJECT");
5763 else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED"))
5764 COMPLETE_WITH("VIEW");
5765 else if (TailMatches("CREATE|ALTER|DROP", "PROPERTY"))
5766 COMPLETE_WITH("GRAPH");
5767 else if (TailMatches("CREATE|ALTER|DROP", "TEXT"))
5768 COMPLETE_WITH("SEARCH");
5769 else if (TailMatches("CREATE|ALTER|DROP", "USER"))
5770 COMPLETE_WITH("MAPPING FOR");
5771 }
5772 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny))
5773 {
5774 if (TailMatches("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
5775 COMPLETE_WITH("WRAPPER");
5776 else if (TailMatches("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
5777 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
5778 else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING"))
5779 COMPLETE_WITH("FOR");
5780 }
5781 else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*"))
5783 else if (TailMatchesCS("\\password"))
5785 else if (TailMatchesCS("\\pset"))
5786 COMPLETE_WITH_CS("border", "columns", "csv_fieldsep",
5787 "display_false", "display_true", "expanded",
5788 "fieldsep", "fieldsep_zero", "footer", "format",
5789 "linestyle", "null", "numericlocale",
5790 "pager", "pager_min_lines",
5791 "recordsep", "recordsep_zero",
5792 "tableattr", "title", "tuples_only",
5793 "unicode_border_linestyle",
5794 "unicode_column_linestyle",
5795 "unicode_header_linestyle",
5796 "xheader_width");
5797 else if (TailMatchesCS("\\pset", MatchAny))
5798 {
5799 if (TailMatchesCS("format"))
5800 COMPLETE_WITH_CS("aligned", "asciidoc", "csv", "html", "latex",
5801 "latex-longtable", "troff-ms", "unaligned",
5802 "wrapped");
5803 else if (TailMatchesCS("xheader_width"))
5804 COMPLETE_WITH_CS("full", "column", "page");
5805 else if (TailMatchesCS("linestyle"))
5806 COMPLETE_WITH_CS("ascii", "old-ascii", "unicode");
5807 else if (TailMatchesCS("pager"))
5808 COMPLETE_WITH_CS("on", "off", "always");
5809 else if (TailMatchesCS("unicode_border_linestyle|"
5810 "unicode_column_linestyle|"
5811 "unicode_header_linestyle"))
5812 COMPLETE_WITH_CS("single", "double");
5813 }
5814 else if (TailMatchesCS("\\unset"))
5815 matches = complete_from_variables(text, "", "", true);
5816 else if (TailMatchesCS("\\set"))
5817 matches = complete_from_variables(text, "", "", false);
5818 else if (TailMatchesCS("\\set", MatchAny))
5819 {
5820 if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|SHOW_ALL_RESULTS|"
5821 "SINGLELINE|SINGLESTEP"))
5822 COMPLETE_WITH_CS("on", "off");
5823 else if (TailMatchesCS("COMP_KEYWORD_CASE"))
5824 COMPLETE_WITH_CS("lower", "upper",
5825 "preserve-lower", "preserve-upper");
5826 else if (TailMatchesCS("ECHO"))
5827 COMPLETE_WITH_CS("errors", "queries", "all", "none");
5828 else if (TailMatchesCS("ECHO_HIDDEN"))
5829 COMPLETE_WITH_CS("noexec", "off", "on");
5830 else if (TailMatchesCS("HISTCONTROL"))
5831 COMPLETE_WITH_CS("ignorespace", "ignoredups",
5832 "ignoreboth", "none");
5833 else if (TailMatchesCS("ON_ERROR_ROLLBACK"))
5834 COMPLETE_WITH_CS("on", "off", "interactive");
5835 else if (TailMatchesCS("SHOW_CONTEXT"))
5836 COMPLETE_WITH_CS("never", "errors", "always");
5837 else if (TailMatchesCS("VERBOSITY"))
5838 COMPLETE_WITH_CS("default", "verbose", "terse", "sqlstate");
5839 }
5840 else if (TailMatchesCS("\\sf*"))
5842 else if (TailMatchesCS("\\sv*"))
5844 else if (TailMatchesCS("\\cd|\\e|\\edit|\\g|\\gx|\\i|\\include|"
5845 "\\ir|\\include_relative|\\o|\\out|"
5846 "\\s|\\w|\\write|\\lo_import") ||
5847 TailMatchesCS("\\lo_export", MatchAny))
5848 COMPLETE_WITH_FILES("\\", false);
5849
5850 /* gen_tabcomplete.pl ends special processing here */
5851 /* END GEN_TABCOMPLETE */
5852
5853 return matches;
5854}
5855
5856
5857/*
5858 * GENERATOR FUNCTIONS
5859 *
5860 * These functions do all the actual work of completing the input. They get
5861 * passed the text so far and the count how many times they have been called
5862 * so far with the same text.
5863 * If you read the above carefully, you'll see that these don't get called
5864 * directly but through the readline interface.
5865 * The return value is expected to be the full completion of the text, going
5866 * through a list each time, or NULL if there are no more matches. The string
5867 * will be free()'d by readline, so you must run it through strdup() or
5868 * something of that sort.
5869 */
5870
5871/*
5872 * Common routine for create_command_generator and drop_command_generator.
5873 * Entries that have 'excluded' flags are not returned.
5874 */
5875static char *
5876create_or_drop_command_generator(const char *text, int state, uint32 excluded)
5877{
5878 static int list_index,
5879 string_length;
5880 const char *name;
5881
5882 /* If this is the first time for this completion, init some values */
5883 if (state == 0)
5884 {
5885 list_index = 0;
5886 string_length = strlen(text);
5887 }
5888
5889 /* find something that matches */
5890 while ((name = words_after_create[list_index++].name))
5891 {
5892 if ((pg_strncasecmp(name, text, string_length) == 0) &&
5893 !(words_after_create[list_index - 1].flags & excluded))
5895 }
5896 /* if nothing matches, return NULL */
5897 return NULL;
5898}
5899
5900/*
5901 * This one gives you one from a list of things you can put after CREATE
5902 * as defined above.
5903 */
5904static char *
5905create_command_generator(const char *text, int state)
5906{
5908}
5909
5910/*
5911 * This function gives you a list of things you can put after a DROP command.
5912 */
5913static char *
5914drop_command_generator(const char *text, int state)
5915{
5917}
5918
5919/*
5920 * This function gives you a list of things you can put after an ALTER command.
5921 */
5922static char *
5923alter_command_generator(const char *text, int state)
5924{
5926}
5927
5928/*
5929 * These functions generate lists using server queries.
5930 * They are all wrappers for _complete_from_query.
5931 */
5932
5933static char *
5934complete_from_query(const char *text, int state)
5935{
5936 /* query is assumed to work for any server version */
5939}
5940
5941static char *
5943{
5945
5946 /* Find appropriate array element */
5947 while (pset.sversion < vquery->min_server_version)
5948 vquery++;
5949 /* Fail completion if server is too old */
5950 if (vquery->query == NULL)
5951 return NULL;
5952
5955}
5956
5957static char *
5958complete_from_schema_query(const char *text, int state)
5959{
5960 /* query is assumed to work for any server version */
5963}
5964
5965static char *
5967{
5969
5970 /* Find appropriate array element */
5971 while (pset.sversion < squery->min_server_version)
5972 squery++;
5973 /* Fail completion if server is too old */
5974 if (squery->catname == NULL)
5975 return NULL;
5976
5979}
5980
5981
5982/*
5983 * This creates a list of matching things, according to a query described by
5984 * the initial arguments. The caller has already done any work needed to
5985 * select the appropriate query for the server's version.
5986 *
5987 * The query can be one of two kinds:
5988 *
5989 * 1. A simple query, which must contain a restriction clause of the form
5990 * output LIKE '%s'
5991 * where "output" is the same string that the query returns. The %s
5992 * will be replaced by a LIKE pattern to match the already-typed text.
5993 * There can be a second '%s', which will be replaced by a suitably-escaped
5994 * version of the string provided in completion_ref_object. If there is a
5995 * third '%s', it will be replaced by a suitably-escaped version of the string
5996 * provided in completion_ref_schema. Those strings should be set up
5997 * by calling set_completion_reference or set_completion_reference_verbatim.
5998 * Simple queries should return a single column of matches. If "verbatim"
5999 * is true, the matches are returned as-is; otherwise, they are taken to
6000 * be SQL identifiers and quoted if necessary.
6001 *
6002 * 2. A schema query used for completion of both schema and relation names.
6003 * This is represented by a SchemaQuery object; see that typedef for details.
6004 *
6005 * See top of file for examples of both kinds of query.
6006 *
6007 * In addition to the query itself, we accept a null-terminated array of
6008 * literal keywords, which will be returned if they match the input-so-far
6009 * (case insensitively). (These are in addition to keywords specified
6010 * within the schema_query, if any.)
6011 *
6012 * If "verbatim" is true, then we use the given text as-is to match the
6013 * query results; otherwise we parse it as a possibly-qualified identifier,
6014 * and reconstruct suitable quoting afterward.
6015 *
6016 * "text" and "state" are supplied by Readline. "text" is the word we are
6017 * trying to complete. "state" is zero on first call, nonzero later.
6018 *
6019 * readline will call this repeatedly with the same text and varying
6020 * state. On each call, we are supposed to return a malloc'd string
6021 * that is a candidate completion. Return NULL when done.
6022 */
6023static char *
6026 const char *const *keywords,
6027 bool verbatim,
6028 const char *text, int state)
6029{
6030 static int list_index,
6033 num_keywords;
6034 static PGresult *result = NULL;
6035 static bool non_empty_object;
6036 static bool schemaquoted;
6037 static bool objectquoted;
6038
6039 /*
6040 * If this is the first time for this completion, we fetch a list of our
6041 * "things" from the backend.
6042 */
6043 if (state == 0)
6044 {
6046 char *schemaname;
6047 char *objectname;
6048 char *e_object_like;
6049 char *e_schemaname;
6050 char *e_ref_object;
6051 char *e_ref_schema;
6052
6053 /* Reset static state, ensuring no memory leaks */
6054 list_index = 0;
6055 num_schema_only = 0;
6056 num_query_other = 0;
6057 num_keywords = 0;
6058 PQclear(result);
6059 result = NULL;
6060
6061 /* Parse text, splitting into schema and object name if needed */
6062 if (verbatim)
6063 {
6065 schemaname = NULL;
6066 }
6067 else
6068 {
6070 &schemaname, &objectname,
6072 }
6073
6074 /* Remember whether the user has typed anything in the object part */
6075 non_empty_object = (*objectname != '\0');
6076
6077 /*
6078 * Convert objectname to a LIKE prefix pattern (e.g. 'foo%'), and set
6079 * up suitably-escaped copies of all the strings we need.
6080 */
6082
6083 if (schemaname)
6084 e_schemaname = escape_string(schemaname);
6085 else
6087
6090 else
6092
6095 else
6097
6099
6100 if (schema_query)
6101 {
6103
6104 /*
6105 * We issue different queries depending on whether the input is
6106 * already qualified or not. schema_query gives us the pieces to
6107 * assemble.
6108 */
6109 if (schemaname == NULL || schema_query->namespace == NULL)
6110 {
6111 /* Get unqualified names matching the input-so-far */
6113 if (schema_query->use_distinct)
6114 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
6116 "%s, NULL::pg_catalog.text FROM %s",
6117 schema_query->result,
6118 schema_query->catname);
6119 if (schema_query->refnamespace && completion_ref_schema)
6121 ", pg_catalog.pg_namespace nr");
6123 if (schema_query->selcondition)
6124 appendPQExpBuffer(&query_buffer, "%s AND ",
6125 schema_query->selcondition);
6126 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s'",
6127 schema_query->result,
6129 if (schema_query->viscondition)
6130 appendPQExpBuffer(&query_buffer, " AND %s",
6131 schema_query->viscondition);
6132 if (schema_query->refname)
6133 {
6135 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
6136 schema_query->refname, e_ref_object);
6137 if (schema_query->refnamespace && completion_ref_schema)
6139 " AND %s = nr.oid AND nr.nspname = '%s'",
6140 schema_query->refnamespace,
6141 e_ref_schema);
6142 else if (schema_query->refviscondition)
6144 " AND %s",
6145 schema_query->refviscondition);
6146 }
6147
6148 /*
6149 * When fetching relation names, suppress system catalogs
6150 * unless the input-so-far begins with "pg_". This is a
6151 * compromise between not offering system catalogs for
6152 * completion at all, and having them swamp the result when
6153 * the input is just "p".
6154 */
6155 if (strcmp(schema_query->catname,
6156 "pg_catalog.pg_class c") == 0 &&
6157 strncmp(objectname, "pg_", 3) != 0)
6158 {
6160 " AND c.relnamespace <> (SELECT oid FROM"
6161 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
6162 }
6163
6164 /*
6165 * If the target object type can be schema-qualified, add in
6166 * schema names matching the input-so-far.
6167 */
6168 if (schema_query->namespace)
6169 {
6170 appendPQExpBuffer(&query_buffer, "\nUNION ALL\n"
6171 "SELECT NULL::pg_catalog.text, n.nspname "
6172 "FROM pg_catalog.pg_namespace n "
6173 "WHERE n.nspname LIKE '%s'",
6175
6176 /*
6177 * Likewise, suppress system schemas unless the
6178 * input-so-far begins with "pg_".
6179 */
6180 if (strncmp(objectname, "pg_", 3) != 0)
6182 " AND n.nspname NOT LIKE E'pg\\\\_%'");
6183
6184 /*
6185 * Since we're matching these schema names to the object
6186 * name, handle their quoting using the object name's
6187 * quoting state.
6188 */
6190 }
6191 }
6192 else
6193 {
6194 /* Input is qualified, so produce only qualified names */
6196 if (schema_query->use_distinct)
6197 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
6198 appendPQExpBuffer(&query_buffer, "%s, n.nspname "
6199 "FROM %s, pg_catalog.pg_namespace n",
6200 schema_query->result,
6201 schema_query->catname);
6202 if (schema_query->refnamespace && completion_ref_schema)
6204 ", pg_catalog.pg_namespace nr");
6205 appendPQExpBuffer(&query_buffer, " WHERE %s = n.oid AND ",
6206 schema_query->namespace);
6207 if (schema_query->selcondition)
6208 appendPQExpBuffer(&query_buffer, "%s AND ",
6209 schema_query->selcondition);
6210 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s' AND ",
6211 schema_query->result,
6213 appendPQExpBuffer(&query_buffer, "n.nspname = '%s'",
6214 e_schemaname);
6215 if (schema_query->refname)
6216 {
6218 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
6219 schema_query->refname, e_ref_object);
6220 if (schema_query->refnamespace && completion_ref_schema)
6222 " AND %s = nr.oid AND nr.nspname = '%s'",
6223 schema_query->refnamespace,
6224 e_ref_schema);
6225 else if (schema_query->refviscondition)
6227 " AND %s",
6228 schema_query->refviscondition);
6229 }
6230 }
6231 }
6232 else
6233 {
6235 /* simple_query is an sprintf-style format string */
6239 }
6240
6241 /* Limit the number of records in the result */
6242 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
6244
6245 /* Finally, we can issue the query */
6247
6248 /* Clean up */
6250 free(schemaname);
6256 }
6257
6258 /* Return the next result, if any, but not if the query failed */
6260 {
6261 int nskip;
6262
6263 while (list_index < PQntuples(result))
6264 {
6265 const char *item = NULL;
6266 const char *nsp = NULL;
6267
6268 if (!PQgetisnull(result, list_index, 0))
6269 item = PQgetvalue(result, list_index, 0);
6270 if (PQnfields(result) > 1 &&
6271 !PQgetisnull(result, list_index, 1))
6272 nsp = PQgetvalue(result, list_index, 1);
6273 list_index++;
6274
6275 /* In verbatim mode, we return all the items as-is */
6276 if (verbatim)
6277 {
6279 return pg_strdup(item);
6280 }
6281
6282 /*
6283 * In normal mode, a name requiring quoting will be returned only
6284 * if the input was empty or quoted. Otherwise the user might see
6285 * completion inserting a quote she didn't type, which is
6286 * surprising. This restriction also dodges some odd behaviors of
6287 * some versions of readline/libedit.
6288 */
6289 if (non_empty_object)
6290 {
6291 if (item && !objectquoted && identifier_needs_quotes(item))
6292 continue;
6294 continue;
6295 }
6296
6297 /* Count schema-only results for hack below */
6298 if (item == NULL && nsp != NULL)
6300 else
6302
6304 }
6305
6306 /*
6307 * When the query result is exhausted, check for hard-wired keywords.
6308 * These will only be returned if they match the input-so-far,
6309 * ignoring case.
6310 */
6311 nskip = list_index - PQntuples(result);
6312 if (schema_query && schema_query->keywords)
6313 {
6314 const char *const *itemp = schema_query->keywords;
6315
6316 while (*itemp)
6317 {
6318 const char *item = *itemp++;
6319
6320 if (nskip-- > 0)
6321 continue;
6322 list_index++;
6323 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6324 {
6325 num_keywords++;
6326 return pg_strdup_keyword_case(item, text);
6327 }
6328 }
6329 }
6330 if (keywords)
6331 {
6332 const char *const *itemp = keywords;
6333
6334 while (*itemp)
6335 {
6336 const char *item = *itemp++;
6337
6338 if (nskip-- > 0)
6339 continue;
6340 list_index++;
6341 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6342 {
6343 num_keywords++;
6344 return pg_strdup_keyword_case(item, text);
6345 }
6346 }
6347 }
6348 }
6349
6350 /*
6351 * Hack: if we returned only bare schema names, don't let Readline add a
6352 * space afterwards. Otherwise the schema will stop being part of the
6353 * completion subject text, which is not what we want.
6354 */
6355 if (num_schema_only > 0 && num_query_other == 0 && num_keywords == 0)
6357
6358 /* No more matches, so free the result structure and return null */
6359 PQclear(result);
6360 result = NULL;
6361 return NULL;
6362}
6363
6364
6365/*
6366 * Set up completion_ref_object and completion_ref_schema
6367 * by parsing the given word. These variables can then be
6368 * used in a query passed to _complete_from_query.
6369 */
6370static void
6371set_completion_reference(const char *word)
6372{
6373 bool schemaquoted,
6375
6379}
6380
6381/*
6382 * Set up completion_ref_object when it should just be
6383 * the given word verbatim.
6384 */
6385static void
6387{
6390}
6391
6392
6393/*
6394 * This function returns in order one of a fixed, NULL pointer terminated list
6395 * of strings (if matching). This can be used if there are only a fixed number
6396 * SQL words that can appear at certain spot.
6397 */
6398static char *
6399complete_from_list(const char *text, int state)
6400{
6401 static int string_length,
6402 list_index,
6403 matches;
6404 static bool casesensitive;
6405 const char *item;
6406
6407 /* need to have a list */
6409
6410 /* Initialization */
6411 if (state == 0)
6412 {
6413 list_index = 0;
6414 string_length = strlen(text);
6416 matches = 0;
6417 }
6418
6419 while ((item = completion_charpp[list_index++]))
6420 {
6421 /* First pass is case sensitive */
6422 if (casesensitive && strncmp(text, item, string_length) == 0)
6423 {
6424 matches++;
6425 return pg_strdup(item);
6426 }
6427
6428 /* Second pass is case insensitive, don't bother counting matches */
6429 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
6430 {
6432 return pg_strdup(item);
6433 else
6434
6435 /*
6436 * If case insensitive matching was requested initially,
6437 * adjust the case according to setting.
6438 */
6439 return pg_strdup_keyword_case(item, text);
6440 }
6441 }
6442
6443 /*
6444 * No matches found. If we're not case insensitive already, lets switch to
6445 * being case insensitive and try again
6446 */
6447 if (casesensitive && matches == 0)
6448 {
6449 casesensitive = false;
6450 list_index = 0;
6451 state++;
6452 return complete_from_list(text, state);
6453 }
6454
6455 /* If no more matches, return null. */
6456 return NULL;
6457}
6458
6459
6460/*
6461 * This function returns one fixed string the first time even if it doesn't
6462 * match what's there, and nothing the second time. The string
6463 * to be used must be in completion_charp.
6464 *
6465 * If the given string is "", this has the effect of preventing readline
6466 * from doing any completion. (Without this, readline tries to do filename
6467 * completion which is seldom the right thing.)
6468 *
6469 * If the given string is not empty, readline will replace whatever the
6470 * user typed with that string. This behavior might be useful if it's
6471 * completely certain that we know what must appear at a certain spot,
6472 * so that it's okay to overwrite misspellings. In practice, given the
6473 * relatively lame parsing technology used in this file, the level of
6474 * certainty is seldom that high, so that you probably don't want to
6475 * use this. Use complete_from_list with a one-element list instead;
6476 * that won't try to auto-correct "misspellings".
6477 */
6478static char *
6479complete_from_const(const char *text, int state)
6480{
6482 if (state == 0)
6483 {
6486 else
6487
6488 /*
6489 * If case insensitive matching was requested initially, adjust
6490 * the case according to setting.
6491 */
6493 }
6494 else
6495 return NULL;
6496}
6497
6498
6499/*
6500 * This function appends the variable name with prefix and suffix to
6501 * the variable names array.
6502 */
6503static void
6504append_variable_names(char ***varnames, int *nvars,
6505 int *maxvars, const char *varname,
6506 const char *prefix, const char *suffix)
6507{
6508 if (*nvars >= *maxvars)
6509 {
6510 *maxvars *= 2;
6511 *varnames = pg_realloc_array(*varnames, char *, (*maxvars) + 1);
6512 }
6513
6514 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
6515}
6516
6517
6518/*
6519 * This function supports completion with the name of a psql variable.
6520 * The variable names can be prefixed and suffixed with additional text
6521 * to support quoting usages. If need_value is true, only variables
6522 * that are currently set are included; otherwise, special variables
6523 * (those that have hooks) are included even if currently unset.
6524 */
6525static char **
6526complete_from_variables(const char *text, const char *prefix, const char *suffix,
6527 bool need_value)
6528{
6529 char **matches;
6530 char **varnames;
6531 int nvars = 0;
6532 int maxvars = 100;
6533 int i;
6534 struct _variable *ptr;
6535
6536 varnames = pg_malloc_array(char *, maxvars + 1);
6537
6538 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
6539 {
6540 if (need_value && !(ptr->value))
6541 continue;
6542 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
6543 prefix, suffix);
6544 }
6545
6546 varnames[nvars] = NULL;
6547 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
6548
6549 for (i = 0; i < nvars; i++)
6550 free(varnames[i]);
6551 free(varnames);
6552
6553 return matches;
6554}
6555
6556
6557/*
6558 * This function returns in order one of a fixed, NULL pointer terminated list
6559 * of string that matches file names or optionally specified list of keywords.
6560 *
6561 * If completion_charpp is set to a null-terminated array of literal keywords,
6562 * those keywords are added to the completion results alongside filenames if
6563 * they case-insensitively match the current input.
6564 */
6565static char *
6566complete_from_files(const char *text, int state)
6567{
6568 static int list_index;
6569 static bool files_done;
6570 const char *item;
6571
6572 /* Initialization */
6573 if (state == 0)
6574 {
6575 list_index = 0;
6576 files_done = false;
6577 }
6578
6579 if (!files_done)
6580 {
6582
6583 /* Return a filename that matches */
6584 if (result)
6585 return result;
6586
6587 /* There are no more matching files */
6588 files_done = true;
6589 }
6590
6591 if (!completion_charpp)
6592 return NULL;
6593
6594 /*
6595 * Check for hard-wired keywords. These will only be returned if they
6596 * match the input-so-far, ignoring case.
6597 */
6598 while ((item = completion_charpp[list_index++]))
6599 {
6600 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6601 {
6602 completion_force_quote = false;
6603 return pg_strdup_keyword_case(item, text);
6604 }
6605 }
6606
6607 return NULL;
6608}
6609
6610/*
6611 * This function wraps rl_filename_completion_function() to strip quotes from
6612 * the input before searching for matches and to quote any matches for which
6613 * the consuming command will require it.
6614 *
6615 * Caller must set completion_charp to a zero- or one-character string
6616 * containing the escape character. This is necessary since \copy has no
6617 * escape character, but every other backslash command recognizes "\" as an
6618 * escape character.
6619 *
6620 * Caller must also set completion_force_quote to indicate whether to force
6621 * quotes around the result. (The SQL COPY command requires that.)
6622 */
6623static char *
6624_complete_from_files(const char *text, int state)
6625{
6626#ifdef USE_FILENAME_QUOTING_FUNCTIONS
6627
6628 /*
6629 * If we're using a version of Readline that supports filename quoting
6630 * hooks, rely on those, and invoke rl_filename_completion_function()
6631 * without messing with its arguments. Readline does stuff internally
6632 * that does not work well at all if we try to handle dequoting here.
6633 * Instead, Readline will call quote_file_name() and dequote_file_name()
6634 * (see below) at appropriate times.
6635 *
6636 * ... or at least, mostly it will. There are some paths involving
6637 * unmatched file names in which Readline never calls quote_file_name(),
6638 * and if left to its own devices it will incorrectly append a quote
6639 * anyway. Set rl_completion_suppress_quote to prevent that. If we do
6640 * get to quote_file_name(), we'll clear this again. (Yes, this seems
6641 * like it's working around Readline bugs.)
6642 */
6643#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
6645#endif
6646
6647 /* If user typed a quote, force quoting (never remove user's quote) */
6648 if (*text == '\'')
6650
6652#else
6653
6654 /*
6655 * Otherwise, we have to do the best we can.
6656 */
6657 static const char *unquoted_text;
6658 char *unquoted_match;
6659 char *ret = NULL;
6660
6661 /* If user typed a quote, force quoting (never remove user's quote) */
6662 if (*text == '\'')
6664
6665 if (state == 0)
6666 {
6667 /* Initialization: stash the unquoted input. */
6669 false, true, pset.encoding);
6670 /* expect a NULL return for the empty string only */
6671 if (!unquoted_text)
6672 {
6673 Assert(*text == '\0');
6675 }
6676 }
6677
6679 if (unquoted_match)
6680 {
6681 struct stat statbuf;
6682 bool is_dir = (stat(unquoted_match, &statbuf) == 0 &&
6683 S_ISDIR(statbuf.st_mode) != 0);
6684
6685 /* Re-quote the result, if needed. */
6686 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
6687 '\'', *completion_charp,
6689 pset.encoding);
6690 if (ret)
6692 else
6693 ret = unquoted_match;
6694
6695 /*
6696 * If it's a directory, replace trailing quote with a slash; this is
6697 * usually more convenient. (If we didn't quote, leave this to
6698 * libedit.)
6699 */
6700 if (*ret == '\'' && is_dir)
6701 {
6702 char *retend = ret + strlen(ret) - 1;
6703
6704 Assert(*retend == '\'');
6705 *retend = '/';
6706 /* Prevent libedit from adding a space, too */
6708 }
6709 }
6710
6711 return ret;
6712#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
6713}
6714
6715
6716/* HELPER FUNCTIONS */
6717
6718
6719/*
6720 * Make a pg_strdup copy of s and convert the case according to
6721 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
6722 */
6723static char *
6724pg_strdup_keyword_case(const char *s, const char *ref)
6725{
6726 char *ret,
6727 *p;
6728 unsigned char first = ref[0];
6729
6730 ret = pg_strdup(s);
6731
6736 {
6737 for (p = ret; *p; p++)
6738 *p = pg_tolower((unsigned char) *p);
6739 }
6740 else
6741 {
6742 for (p = ret; *p; p++)
6743 *p = pg_toupper((unsigned char) *p);
6744 }
6745
6746 return ret;
6747}
6748
6749
6750/*
6751 * escape_string - Escape argument for use as string literal.
6752 *
6753 * The returned value has to be freed.
6754 */
6755static char *
6756escape_string(const char *text)
6757{
6758 size_t text_length;
6759 char *result;
6760
6762
6763 result = pg_malloc(text_length * 2 + 1);
6765
6766 return result;
6767}
6768
6769
6770/*
6771 * make_like_pattern - Convert argument to a LIKE prefix pattern.
6772 *
6773 * We escape _ and % in the given text by backslashing, append a % to
6774 * represent "any subsequent characters", and then pass the string through
6775 * escape_string() so it's ready to insert in a query. The result needs
6776 * to be freed.
6777 */
6778static char *
6779make_like_pattern(const char *word)
6780{
6781 char *result;
6782 char *buffer = pg_malloc(strlen(word) * 2 + 2);
6783 char *bptr = buffer;
6784
6785 while (*word)
6786 {
6787 if (*word == '_' || *word == '%')
6788 *bptr++ = '\\';
6789 if (IS_HIGHBIT_SET(*word))
6790 {
6791 /*
6792 * Transfer multibyte characters without further processing, to
6793 * avoid getting confused in unsafe client encodings.
6794 */
6796
6797 while (chlen-- > 0)
6798 *bptr++ = *word++;
6799 }
6800 else
6801 *bptr++ = *word++;
6802 }
6803 *bptr++ = '%';
6804 *bptr = '\0';
6805
6806 result = escape_string(buffer);
6807 free(buffer);
6808 return result;
6809}
6810
6811
6812/*
6813 * parse_identifier - Parse a possibly-schema-qualified SQL identifier.
6814 *
6815 * This involves splitting off the schema name if present, de-quoting,
6816 * and downcasing any unquoted text. We are a bit laxer than the backend
6817 * in that we allow just portions of a name to be quoted --- that's because
6818 * psql metacommands have traditionally behaved that way.
6819 *
6820 * Outputs are a malloc'd schema name (NULL if none), malloc'd object name,
6821 * and booleans telling whether any part of the schema and object name was
6822 * double-quoted.
6823 */
6824static void
6825parse_identifier(const char *ident,
6826 char **schemaname, char **objectname,
6827 bool *schemaquoted, bool *objectquoted)
6828{
6829 size_t buflen = strlen(ident) + 1;
6831 char *sname;
6832 char *oname;
6833 char *optr;
6834 bool inquotes;
6835
6836 /* Initialize, making a certainly-large-enough output buffer */
6837 sname = NULL;
6838 oname = pg_malloc(buflen);
6839 *schemaquoted = *objectquoted = false;
6840 /* Scan */
6841 optr = oname;
6842 inquotes = false;
6843 while (*ident)
6844 {
6845 unsigned char ch = (unsigned char) *ident++;
6846
6847 if (ch == '"')
6848 {
6849 if (inquotes && *ident == '"')
6850 {
6851 /* two quote marks within a quoted identifier = emit quote */
6852 *optr++ = '"';
6853 ident++;
6854 }
6855 else
6856 {
6857 inquotes = !inquotes;
6858 *objectquoted = true;
6859 }
6860 }
6861 else if (ch == '.' && !inquotes)
6862 {
6863 /* Found a schema name, transfer it to sname / *schemaquoted */
6864 *optr = '\0';
6865 free(sname); /* drop any catalog name */
6866 sname = oname;
6867 oname = pg_malloc(buflen);
6868 optr = oname;
6870 *objectquoted = false;
6871 }
6872 else if (!enc_is_single_byte && IS_HIGHBIT_SET(ch))
6873 {
6874 /*
6875 * Transfer multibyte characters without further processing. They
6876 * wouldn't be affected by our downcasing rule anyway, and this
6877 * avoids possibly doing the wrong thing in unsafe client
6878 * encodings.
6879 */
6881
6882 *optr++ = (char) ch;
6883 while (--chlen > 0)
6884 *optr++ = *ident++;
6885 }
6886 else
6887 {
6888 if (!inquotes)
6889 {
6890 /*
6891 * This downcasing transformation should match the backend's
6892 * downcase_identifier() as best we can. We do not know the
6893 * backend's locale, though, so it's necessarily approximate.
6894 * We assume that psql is operating in the same locale and
6895 * encoding as the backend.
6896 */
6897 if (ch >= 'A' && ch <= 'Z')
6898 ch += 'a' - 'A';
6900 ch = tolower(ch);
6901 }
6902 *optr++ = (char) ch;
6903 }
6904 }
6905
6906 *optr = '\0';
6907 *schemaname = sname;
6908 *objectname = oname;
6909}
6910
6911
6912/*
6913 * requote_identifier - Reconstruct a possibly-schema-qualified SQL identifier.
6914 *
6915 * Build a malloc'd string containing the identifier, with quoting applied
6916 * as necessary. This is more or less the inverse of parse_identifier;
6917 * in particular, if an input component was quoted, we'll quote the output
6918 * even when that isn't strictly required.
6919 *
6920 * Unlike parse_identifier, we handle the case where a schema and no
6921 * object name is provided, producing just "schema.".
6922 */
6923static char *
6924requote_identifier(const char *schemaname, const char *objectname,
6925 bool quote_schema, bool quote_object)
6926{
6927 char *result;
6928 size_t buflen = 1; /* count the trailing \0 */
6929 char *ptr;
6930
6931 /*
6932 * We could use PQescapeIdentifier for some of this, but not all, and it
6933 * adds more notational cruft than it seems worth.
6934 */
6935 if (schemaname)
6936 {
6937 buflen += strlen(schemaname) + 1; /* +1 for the dot */
6938 if (!quote_schema)
6940 if (quote_schema)
6941 {
6942 buflen += 2; /* account for quote marks */
6943 for (const char *p = schemaname; *p; p++)
6944 {
6945 if (*p == '"')
6946 buflen++;
6947 }
6948 }
6949 }
6950 if (objectname)
6951 {
6952 buflen += strlen(objectname);
6953 if (!quote_object)
6955 if (quote_object)
6956 {
6957 buflen += 2; /* account for quote marks */
6958 for (const char *p = objectname; *p; p++)
6959 {
6960 if (*p == '"')
6961 buflen++;
6962 }
6963 }
6964 }
6965 result = pg_malloc(buflen);
6966 ptr = result;
6967 if (schemaname)
6968 {
6969 if (quote_schema)
6970 *ptr++ = '"';
6971 for (const char *p = schemaname; *p; p++)
6972 {
6973 *ptr++ = *p;
6974 if (*p == '"')
6975 *ptr++ = '"';
6976 }
6977 if (quote_schema)
6978 *ptr++ = '"';
6979 *ptr++ = '.';
6980 }
6981 if (objectname)
6982 {
6983 if (quote_object)
6984 *ptr++ = '"';
6985 for (const char *p = objectname; *p; p++)
6986 {
6987 *ptr++ = *p;
6988 if (*p == '"')
6989 *ptr++ = '"';
6990 }
6991 if (quote_object)
6992 *ptr++ = '"';
6993 }
6994 *ptr = '\0';
6995 return result;
6996}
6997
6998
6999/*
7000 * Detect whether an identifier must be double-quoted.
7001 *
7002 * Note we'll quote anything that's not ASCII; the backend's quote_ident()
7003 * does the same. Perhaps this could be relaxed in future.
7004 */
7005static bool
7006identifier_needs_quotes(const char *ident)
7007{
7008 int kwnum;
7009
7010 /* Check syntax. */
7011 if (!((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_'))
7012 return true;
7013 if (strspn(ident, "abcdefghijklmnopqrstuvwxyz0123456789_$") != strlen(ident))
7014 return true;
7015
7016 /*
7017 * Check for keyword. We quote keywords except for unreserved ones.
7018 *
7019 * It is possible that our keyword list doesn't quite agree with the
7020 * server's, but this should be close enough for tab-completion purposes.
7021 *
7022 * Note: ScanKeywordLookup() does case-insensitive comparison, but that's
7023 * fine, since we already know we have all-lower-case.
7024 */
7026
7028 return true;
7029
7030 return false;
7031}
7032
7033
7034/*
7035 * Execute a query, returning NULL if there was any error.
7036 * This should be the preferred way of talking to the database in this file.
7037 */
7038static PGresult *
7039exec_query(const char *query)
7040{
7042
7043 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
7044 return NULL;
7045
7046 result = PQexec(pset.db, query);
7047
7049 {
7050 /*
7051 * Printing an error while the user is typing would be quite annoying,
7052 * so we don't. This does complicate debugging of this code; but you
7053 * can look in the server log instead.
7054 */
7055#ifdef NOT_USED
7056 pg_log_error("tab completion query failed: %s\nQuery was:\n%s",
7057 PQerrorMessage(pset.db), query);
7058#endif
7059 PQclear(result);
7060 result = NULL;
7061 }
7062
7063 return result;
7064}
7065
7066
7067/*
7068 * Parse all the word(s) before point.
7069 *
7070 * Returns a malloc'd array of character pointers that point into the malloc'd
7071 * data array returned to *buffer; caller must free() both of these when done.
7072 * *nwords receives the number of words found, ie, the valid length of the
7073 * return array.
7074 *
7075 * Words are returned right to left, that is, previous_words[0] gets the last
7076 * word before point, previous_words[1] the next-to-last, etc.
7077 */
7078static char **
7079get_previous_words(int point, char **buffer, int *nwords)
7080{
7081 char **previous_words;
7082 char *buf;
7083 char *outptr;
7084 int words_found = 0;
7085 int i;
7086
7087 /*
7088 * If we have anything in tab_completion_query_buf, paste it together with
7089 * rl_line_buffer to construct the full query. Otherwise we can just use
7090 * rl_line_buffer as the input string.
7091 */
7093 {
7095 buf = pg_malloc(point + i + 2);
7097 buf[i++] = '\n';
7099 i += point;
7100 buf[i] = '\0';
7101 /* Readjust point to reference appropriate offset in buf */
7102 point = i;
7103 }
7104 else
7106
7107 /*
7108 * Allocate an array of string pointers and a buffer to hold the strings
7109 * themselves. The worst case is that the line contains only
7110 * non-whitespace WORD_BREAKS characters, making each one a separate word.
7111 * This is usually much more space than we need, but it's cheaper than
7112 * doing a separate malloc() for each word.
7113 */
7115 *buffer = outptr = (char *) pg_malloc(point * 2);
7116
7117 /*
7118 * First we look for a non-word char before the current point. (This is
7119 * probably useless, if readline is on the same page as we are about what
7120 * is a word, but if so it's cheap.)
7121 */
7122 for (i = point - 1; i >= 0; i--)
7123 {
7124 if (strchr(WORD_BREAKS, buf[i]))
7125 break;
7126 }
7127 point = i;
7128
7129 /*
7130 * Now parse words, working backwards, until we hit start of line. The
7131 * backwards scan has some interesting but intentional properties
7132 * concerning parenthesis handling.
7133 */
7134 while (point >= 0)
7135 {
7136 int start,
7137 end;
7138 bool inquotes = false;
7139 int parentheses = 0;
7140
7141 /* now find the first non-space which then constitutes the end */
7142 end = -1;
7143 for (i = point; i >= 0; i--)
7144 {
7145 if (!isspace((unsigned char) buf[i]))
7146 {
7147 end = i;
7148 break;
7149 }
7150 }
7151 /* if no end found, we're done */
7152 if (end < 0)
7153 break;
7154
7155 /*
7156 * Otherwise we now look for the start. The start is either the last
7157 * character before any word-break character going backwards from the
7158 * end, or it's simply character 0. We also handle open quotes and
7159 * parentheses.
7160 */
7161 for (start = end; start > 0; start--)
7162 {
7163 if (buf[start] == '"')
7164 inquotes = !inquotes;
7165 if (!inquotes)
7166 {
7167 if (buf[start] == ')')
7168 parentheses++;
7169 else if (buf[start] == '(')
7170 {
7171 if (--parentheses <= 0)
7172 break;
7173 }
7174 else if (parentheses == 0 &&
7175 strchr(WORD_BREAKS, buf[start - 1]))
7176 break;
7177 }
7178 }
7179
7180 /* Return the word located at start to end inclusive */
7182 i = end - start + 1;
7183 memcpy(outptr, &buf[start], i);
7184 outptr += i;
7185 *outptr++ = '\0';
7186
7187 /* Continue searching */
7188 point = start - 1;
7189 }
7190
7191 /* Release parsing input workspace, if we made one above */
7192 if (buf != rl_line_buffer)
7193 free(buf);
7194
7195 *nwords = words_found;
7196 return previous_words;
7197}
7198
7199/*
7200 * Look up the type for the GUC variable with the passed name.
7201 *
7202 * Returns NULL if the variable is unknown. Otherwise the returned string,
7203 * containing the type, has to be freed.
7204 */
7205static char *
7206get_guctype(const char *varname)
7207{
7209 char *e_varname;
7211 char *guctype = NULL;
7212
7213 e_varname = escape_string(varname);
7214
7217 "SELECT vartype FROM pg_catalog.pg_settings "
7218 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
7219 e_varname);
7220
7223 free(e_varname);
7224
7227
7228 PQclear(result);
7229
7230 return guctype;
7231}
7232
7233#ifdef USE_FILENAME_QUOTING_FUNCTIONS
7234
7235/*
7236 * Quote a filename according to SQL rules, returning a malloc'd string.
7237 * completion_charp must point to escape character or '\0', and
7238 * completion_force_quote must be set correctly, as per comments for
7239 * complete_from_files().
7240 */
7241static char *
7242quote_file_name(char *fname, int match_type, char *quote_pointer)
7243{
7244 char *s;
7245 struct stat statbuf;
7246
7247 /* Quote if needed. */
7248 s = quote_if_needed(fname, " \t\r\n\"`",
7249 '\'', *completion_charp,
7251 pset.encoding);
7252 if (!s)
7253 s = pg_strdup(fname);
7254
7255 /*
7256 * However, some of the time we have to strip the trailing quote from what
7257 * we send back. Never strip the trailing quote if the user already typed
7258 * one; otherwise, suppress the trailing quote if we have multiple/no
7259 * matches (because we don't want to add a quote if the input is seemingly
7260 * unfinished), or if the input was already quoted (because Readline will
7261 * do arguably-buggy things otherwise), or if the file does not exist, or
7262 * if it's a directory.
7263 */
7264 if (*s == '\'' &&
7265 completion_last_char != '\'' &&
7267 (quote_pointer && *quote_pointer == '\'') ||
7268 stat(fname, &statbuf) != 0 ||
7269 S_ISDIR(statbuf.st_mode)))
7270 {
7271 char *send = s + strlen(s) - 1;
7272
7273 Assert(*send == '\'');
7274 *send = '\0';
7275 }
7276
7277 /*
7278 * And now we can let Readline do its thing with possibly adding a quote
7279 * on its own accord. (This covers some additional cases beyond those
7280 * dealt with above.)
7281 */
7282#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
7284#endif
7285
7286 /*
7287 * If user typed a leading quote character other than single quote (i.e.,
7288 * double quote), zap it, so that we replace it with the correct single
7289 * quote.
7290 */
7291 if (quote_pointer && *quote_pointer != '\'')
7292 *quote_pointer = '\0';
7293
7294 return s;
7295}
7296
7297/*
7298 * Dequote a filename, if it's quoted.
7299 * completion_charp must point to escape character or '\0', as per
7300 * comments for complete_from_files().
7301 */
7302static char *
7303dequote_file_name(char *fname, int quote_char)
7304{
7305 char *unquoted_fname;
7306
7307 /*
7308 * If quote_char is set, it's not included in "fname". We have to add it
7309 * or strtokx will not interpret the string correctly (notably, it won't
7310 * recognize escapes).
7311 */
7312 if (quote_char == '\'')
7313 {
7314 char *workspace = (char *) pg_malloc(strlen(fname) + 2);
7315
7316 workspace[0] = quote_char;
7317 strcpy(workspace + 1, fname);
7318 unquoted_fname = strtokx(workspace, "", NULL, "'", *completion_charp,
7319 false, true, pset.encoding);
7320 free(workspace);
7321 }
7322 else
7323 unquoted_fname = strtokx(fname, "", NULL, "'", *completion_charp,
7324 false, true, pset.encoding);
7325
7326 /* expect a NULL return for the empty string only */
7327 if (!unquoted_fname)
7328 {
7329 Assert(*fname == '\0');
7330 unquoted_fname = fname;
7331 }
7332
7333 /* readline expects a malloc'd result that it is to free */
7334 return pg_strdup(unquoted_fname);
7335}
7336
7337#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
7338
7339#endif /* USE_READLINE */
bool recognized_connection_string(const char *connstr)
Definition common.c:2707
#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