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 else if (TailMatches("FLUSH_UNLOGGED"))
3278 COMPLETE_WITH("ON", "OFF");
3279 }
3280/* CLOSE */
3281 else if (Matches("CLOSE"))
3283 "ALL");
3284/* CLUSTER */
3285 else if (Matches("CLUSTER"))
3287 "VERBOSE");
3288 else if (Matches("CLUSTER", "VERBOSE") ||
3289 Matches("CLUSTER", "(*)"))
3291 /* If we have CLUSTER <sth>, then add "USING" */
3292 else if (Matches("CLUSTER", MatchAnyExcept("VERBOSE|ON|(|(*)")))
3293 COMPLETE_WITH("USING");
3294 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
3295 else if (Matches("CLUSTER", "VERBOSE|(*)", MatchAny))
3296 COMPLETE_WITH("USING");
3297 /* If we have CLUSTER <sth> USING, then add the index as well */
3298 else if (Matches("CLUSTER", MatchAny, "USING") ||
3299 Matches("CLUSTER", "VERBOSE|(*)", MatchAny, "USING"))
3300 {
3303 }
3304 else if (HeadMatches("CLUSTER", "(*") &&
3305 !HeadMatches("CLUSTER", "(*)"))
3306 {
3307 /*
3308 * This fires if we're in an unfinished parenthesized option list.
3309 * get_previous_words treats a completed parenthesized option list as
3310 * one word, so the above test is correct.
3311 */
3312 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3313 COMPLETE_WITH("VERBOSE");
3314 }
3315
3316/* COMMENT */
3317 else if (Matches("COMMENT"))
3318 COMPLETE_WITH("ON");
3319 else if (Matches("COMMENT", "ON"))
3320 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
3321 "COLUMN", "CONSTRAINT", "CONVERSION", "DATABASE",
3322 "DOMAIN", "EXTENSION", "EVENT TRIGGER",
3323 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
3324 "FUNCTION", "INDEX", "LANGUAGE", "LARGE OBJECT",
3325 "MATERIALIZED VIEW", "OPERATOR", "POLICY",
3326 "PROCEDURE", "PROCEDURAL LANGUAGE", "PROPERTY GRAPH", "PUBLICATION", "ROLE",
3327 "ROUTINE", "RULE", "SCHEMA", "SEQUENCE", "SERVER",
3328 "STATISTICS", "SUBSCRIPTION", "TABLE",
3329 "TABLESPACE", "TEXT SEARCH", "TRANSFORM FOR",
3330 "TRIGGER", "TYPE", "VIEW");
3331 else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
3333 else if (Matches("COMMENT", "ON", "CONSTRAINT"))
3335 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny))
3336 COMPLETE_WITH("ON");
3337 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
3338 {
3341 "DOMAIN");
3342 }
3343 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON", "DOMAIN"))
3345 else if (Matches("COMMENT", "ON", "EVENT", "TRIGGER"))
3347 else if (Matches("COMMENT", "ON", "FOREIGN"))
3348 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3349 else if (Matches("COMMENT", "ON", "FOREIGN", "TABLE"))
3351 else if (Matches("COMMENT", "ON", "MATERIALIZED", "VIEW"))
3353 else if (Matches("COMMENT", "ON", "POLICY"))
3355 else if (Matches("COMMENT", "ON", "POLICY", MatchAny))
3356 COMPLETE_WITH("ON");
3357 else if (Matches("COMMENT", "ON", "POLICY", MatchAny, "ON"))
3358 {
3361 }
3362 else if (Matches("COMMENT", "ON", "PROCEDURAL", "LANGUAGE"))
3364 else if (Matches("COMMENT", "ON", "PROPERTY", "GRAPH"))
3366 else if (Matches("COMMENT", "ON", "RULE", MatchAny))
3367 COMPLETE_WITH("ON");
3368 else if (Matches("COMMENT", "ON", "RULE", MatchAny, "ON"))
3369 {
3372 }
3373 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH"))
3374 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3375 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "CONFIGURATION"))
3377 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "DICTIONARY"))
3379 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "PARSER"))
3381 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "TEMPLATE"))
3383 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR"))
3385 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny))
3386 COMPLETE_WITH("LANGUAGE");
3387 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3388 {
3391 }
3392 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny))
3393 COMPLETE_WITH("ON");
3394 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny, "ON"))
3395 {
3398 }
3399 else if (Matches("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
3400 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3401 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3402 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
3403 COMPLETE_WITH("IS");
3404
3405/* COPY */
3406
3407 /*
3408 * If we have COPY, offer list of tables or "(" (Also cover the analogous
3409 * backslash command).
3410 */
3411 else if (Matches("COPY|\\copy"))
3413 /* Complete COPY ( with legal query commands */
3414 else if (Matches("COPY|\\copy", "("))
3415 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "MERGE INTO", "WITH");
3416 /* Complete COPY <sth> */
3417 else if (Matches("COPY|\\copy", MatchAny))
3418 COMPLETE_WITH("FROM", "TO");
3419 /* Complete COPY|\copy <sth> FROM|TO with filename or STDIN/STDOUT/PROGRAM */
3420 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO"))
3421 {
3422 if (HeadMatches("COPY"))
3423 {
3424 /* COPY requires quoted filename */
3425 if (TailMatches("FROM"))
3426 COMPLETE_WITH_FILES_PLUS("", true, "STDIN", "PROGRAM");
3427 else
3428 COMPLETE_WITH_FILES_PLUS("", true, "STDOUT", "PROGRAM");
3429 }
3430 else
3431 {
3432 /* \copy supports pstdin and pstdout */
3433 if (TailMatches("FROM"))
3434 COMPLETE_WITH_FILES_PLUS("", false, "STDIN", "PSTDIN", "PROGRAM");
3435 else
3436 COMPLETE_WITH_FILES_PLUS("", false, "STDOUT", "PSTDOUT", "PROGRAM");
3437 }
3438 }
3439
3440 /* Complete COPY|\copy <sth> FROM|TO PROGRAM */
3441 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM"))
3442 COMPLETE_WITH_FILES("", HeadMatches("COPY")); /* COPY requires quoted
3443 * filename */
3444
3445 /* Complete COPY <sth> TO [PROGRAM] <sth> */
3446 else if (Matches("COPY|\\copy", MatchAny, "TO", MatchAnyExcept("PROGRAM")) ||
3447 Matches("COPY|\\copy", MatchAny, "TO", "PROGRAM", MatchAny))
3448 COMPLETE_WITH("WITH (");
3449
3450 /* Complete COPY <sth> FROM [PROGRAM] <sth> */
3451 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM")) ||
3452 Matches("COPY|\\copy", MatchAny, "FROM", "PROGRAM", MatchAny))
3453 COMPLETE_WITH("WITH (", "WHERE");
3454
3455 /* Complete COPY <sth> FROM|TO [PROGRAM] filename WITH ( */
3456 else if (HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*") ||
3457 HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*"))
3458 {
3459 if (!HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", MatchAnyExcept("PROGRAM"), "WITH", "(*)") &&
3460 !HeadMatches("COPY|\\copy", MatchAny, "FROM|TO", "PROGRAM", MatchAny, "WITH", "(*)"))
3461 {
3462 /*
3463 * This fires if we're in an unfinished parenthesized option list.
3464 * get_previous_words treats a completed parenthesized option list
3465 * as one word, so the above tests are correct.
3466 */
3467
3468 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3469 {
3470 if (HeadMatches("COPY|\\copy", MatchAny, "FROM"))
3472 else
3474 }
3475
3476 /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
3477 else if (TailMatches("FORMAT"))
3478 COMPLETE_WITH("binary", "csv", "text", "json");
3479
3480 /* Complete COPY <sth> FROM|TO filename WITH (FREEZE */
3481 else if (TailMatches("FREEZE"))
3482 COMPLETE_WITH("true", "false");
3483
3484 /* Complete COPY <sth> FROM|TO filename WITH (HEADER */
3485 else if (TailMatches("HEADER"))
3486 COMPLETE_WITH("true", "false", "MATCH");
3487
3488 /* Complete COPY <sth> FROM filename WITH (ON_ERROR */
3489 else if (TailMatches("ON_ERROR"))
3490 COMPLETE_WITH("stop", "ignore", "set_null");
3491
3492 /* Complete COPY <sth> FROM filename WITH (LOG_VERBOSITY */
3493 else if (TailMatches("LOG_VERBOSITY"))
3494 COMPLETE_WITH("silent", "default", "verbose");
3495 }
3496
3497 /* A completed parenthesized option list should be caught below */
3498 }
3499
3500 /* Complete COPY <sth> FROM [PROGRAM] <sth> WITH (<options>) */
3501 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAnyExcept("PROGRAM"), "WITH", MatchAny) ||
3502 Matches("COPY|\\copy", MatchAny, "FROM", "PROGRAM", MatchAny, "WITH", MatchAny))
3503 COMPLETE_WITH("WHERE");
3504
3505 /* CREATE ACCESS METHOD */
3506 /* Complete "CREATE ACCESS METHOD <name>" */
3507 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny))
3508 COMPLETE_WITH("TYPE");
3509 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
3510 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
3511 COMPLETE_WITH("INDEX", "TABLE");
3512 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
3513 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
3514 COMPLETE_WITH("HANDLER");
3515
3516 /* CREATE COLLATION */
3517 else if (Matches("CREATE", "COLLATION", MatchAny))
3518 COMPLETE_WITH("(", "FROM");
3519 else if (Matches("CREATE", "COLLATION", MatchAny, "FROM"))
3521 else if (HeadMatches("CREATE", "COLLATION", MatchAny, "(*"))
3522 {
3523 if (TailMatches("(|*,"))
3524 COMPLETE_WITH("LOCALE =", "LC_COLLATE =", "LC_CTYPE =",
3525 "PROVIDER =", "DETERMINISTIC =");
3526 else if (TailMatches("PROVIDER", "="))
3527 COMPLETE_WITH("libc", "icu");
3528 else if (TailMatches("DETERMINISTIC", "="))
3529 COMPLETE_WITH("true", "false");
3530 }
3531
3532 /* CREATE DATABASE */
3533 else if (Matches("CREATE", "DATABASE", MatchAny))
3534 COMPLETE_WITH("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
3535 "IS_TEMPLATE", "STRATEGY",
3536 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
3537 "LC_COLLATE", "LC_CTYPE", "LOCALE", "OID",
3538 "LOCALE_PROVIDER", "ICU_LOCALE");
3539
3540 else if (Matches("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
3542 else if (Matches("CREATE", "DATABASE", MatchAny, "STRATEGY"))
3543 COMPLETE_WITH("WAL_LOG", "FILE_COPY");
3544
3545 /* CREATE DOMAIN --- is allowed inside CREATE SCHEMA, so use TailMatches */
3546 else if (TailMatches("CREATE", "DOMAIN", MatchAny))
3547 COMPLETE_WITH("AS");
3548 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "AS"))
3550 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
3551 COMPLETE_WITH("COLLATE", "DEFAULT", "CONSTRAINT",
3552 "NOT NULL", "NULL", "CHECK (");
3553 else if (TailMatches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
3555
3556 /* CREATE EXTENSION */
3557 /* Complete with available extensions rather than installed ones. */
3558 else if (Matches("CREATE", "EXTENSION"))
3560 /* CREATE EXTENSION <name> */
3561 else if (Matches("CREATE", "EXTENSION", MatchAny))
3562 COMPLETE_WITH("WITH SCHEMA", "CASCADE", "VERSION");
3563 /* CREATE EXTENSION <name> VERSION */
3564 else if (Matches("CREATE", "EXTENSION", MatchAny, "VERSION"))
3565 {
3568 }
3569
3570 /* CREATE FOREIGN */
3571 else if (Matches("CREATE", "FOREIGN"))
3572 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3573
3574 /* CREATE FOREIGN DATA WRAPPER */
3575 else if (Matches("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
3576 COMPLETE_WITH("CONNECTION", "HANDLER", "OPTIONS", "VALIDATOR");
3577
3578 /* CREATE FOREIGN TABLE */
3579 else if (Matches("CREATE", "FOREIGN", "TABLE", MatchAny))
3580 COMPLETE_WITH("(", "PARTITION OF");
3581
3582 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
3583 /* First off we complete CREATE UNIQUE with "INDEX" */
3584 else if (TailMatches("CREATE", "UNIQUE"))
3585 COMPLETE_WITH("INDEX");
3586
3587 /*
3588 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
3589 * existing indexes
3590 */
3591 else if (TailMatches("CREATE|UNIQUE", "INDEX"))
3593 "ON", "CONCURRENTLY");
3594
3595 /*
3596 * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
3597 * that indexes can be created on
3598 */
3599 else if (TailMatches("INDEX|CONCURRENTLY", MatchAny, "ON") ||
3600 TailMatches("INDEX|CONCURRENTLY", "ON"))
3602
3603 /*
3604 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
3605 * indexes
3606 */
3607 else if (TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
3609 "ON");
3610 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
3611 else if (TailMatches("CREATE|UNIQUE", "INDEX", MatchAny) ||
3612 TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
3613 COMPLETE_WITH("ON");
3614
3615 /*
3616 * Complete INDEX <name> ON <table> with a list of table columns (which
3617 * should really be in parens)
3618 */
3619 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny) ||
3620 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny))
3621 COMPLETE_WITH("(", "USING");
3622 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny, "(") ||
3623 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
3625 /* same if you put in USING */
3626 else if (TailMatches("ON", MatchAny, "USING", MatchAny, "("))
3628 /* Complete USING with an index method */
3629 else if (TailMatches("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
3630 TailMatches("INDEX", MatchAny, "ON", MatchAny, "USING") ||
3631 TailMatches("INDEX", "ON", MatchAny, "USING"))
3633 else if (TailMatches("ON", MatchAny, "USING", MatchAny) &&
3636 COMPLETE_WITH("(");
3637
3638 /* CREATE OR REPLACE */
3639 else if (Matches("CREATE", "OR"))
3640 COMPLETE_WITH("REPLACE");
3641
3642 /* CREATE POLICY */
3643 /* Complete "CREATE POLICY <name> ON" */
3644 else if (Matches("CREATE", "POLICY", MatchAny))
3645 COMPLETE_WITH("ON");
3646 /* Complete "CREATE POLICY <name> ON <table>" */
3647 else if (Matches("CREATE", "POLICY", MatchAny, "ON"))
3649 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
3650 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny))
3651 COMPLETE_WITH("AS", "FOR", "TO", "USING (", "WITH CHECK (");
3652 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
3653 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
3654 COMPLETE_WITH("PERMISSIVE", "RESTRICTIVE");
3655
3656 /*
3657 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3658 * FOR|TO|USING|WITH CHECK
3659 */
3660 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
3661 COMPLETE_WITH("FOR", "TO", "USING", "WITH CHECK");
3662 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
3663 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
3664 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3665 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
3666 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
3667 COMPLETE_WITH("TO", "WITH CHECK (");
3668 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
3669 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
3670 COMPLETE_WITH("TO", "USING (");
3671 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
3672 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
3673 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3674 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
3675 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
3678 /* Complete "CREATE POLICY <name> ON <table> USING (" */
3679 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
3680 COMPLETE_WITH("(");
3681
3682 /*
3683 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3684 * ALL|SELECT|INSERT|UPDATE|DELETE
3685 */
3686 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
3687 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3688
3689 /*
3690 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3691 * INSERT TO|WITH CHECK"
3692 */
3693 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
3694 COMPLETE_WITH("TO", "WITH CHECK (");
3695
3696 /*
3697 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3698 * SELECT|DELETE TO|USING"
3699 */
3700 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
3701 COMPLETE_WITH("TO", "USING (");
3702
3703 /*
3704 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3705 * ALL|UPDATE TO|USING|WITH CHECK
3706 */
3707 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
3708 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3709
3710 /*
3711 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
3712 * <role>"
3713 */
3714 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
3717
3718 /*
3719 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3720 * USING ("
3721 */
3722 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
3723 COMPLETE_WITH("(");
3724
3725/* CREATE PROPERTY GRAPH */
3726 else if (Matches("CREATE", "PROPERTY"))
3727 COMPLETE_WITH("GRAPH");
3728 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny))
3729 COMPLETE_WITH("VERTEX");
3730 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE"))
3731 COMPLETE_WITH("TABLES");
3732 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES"))
3733 COMPLETE_WITH("(");
3734 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES", "("))
3736 else if (Matches("CREATE", "PROPERTY", "GRAPH", MatchAny, "VERTEX|NODE", "TABLES", "(*)"))
3737 COMPLETE_WITH("EDGE");
3738 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP"))
3739 COMPLETE_WITH("TABLES");
3740 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP", "TABLES"))
3741 COMPLETE_WITH("(");
3742 else if (HeadMatches("CREATE", "PROPERTY", "GRAPH") && TailMatches("EDGE|RELATIONSHIP", "TABLES", "("))
3744
3745/* CREATE PUBLICATION */
3746 else if (Matches("CREATE", "PUBLICATION", MatchAny))
3747 COMPLETE_WITH("FOR TABLE", "FOR TABLES IN SCHEMA", "FOR ALL TABLES", "FOR ALL SEQUENCES", "WITH (");
3748 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
3749 COMPLETE_WITH("TABLE", "TABLES IN SCHEMA", "ALL TABLES", "ALL SEQUENCES");
3750 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL"))
3751 COMPLETE_WITH("TABLES", "SEQUENCES");
3752 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
3753 COMPLETE_WITH("EXCEPT ( TABLE", "WITH (");
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", "("))
3757 COMPLETE_WITH("TABLE");
3758 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE"))
3760 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && ends_with(prev_wd, ','))
3762 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES", "EXCEPT", "(", "TABLE", MatchAnyN) && !ends_with(prev_wd, ','))
3763 COMPLETE_WITH(")");
3764 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES"))
3765 COMPLETE_WITH("IN SCHEMA");
3766 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) && !ends_with(prev_wd, ','))
3767 COMPLETE_WITH("WHERE (", "WITH (");
3768 /* Complete "CREATE PUBLICATION <name> FOR TABLE" with "<table>, ..." */
3769 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE"))
3771
3772 /*
3773 * "CREATE PUBLICATION <name> FOR TABLE <name> WHERE (" - complete with
3774 * table attributes
3775 */
3776 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE"))
3777 COMPLETE_WITH("(");
3778 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "("))
3780 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "(*)"))
3781 COMPLETE_WITH(" WITH (");
3782
3783 /*
3784 * Complete "CREATE PUBLICATION <name> FOR TABLES IN SCHEMA <schema>, ..."
3785 */
3786 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA"))
3788 " AND nspname NOT LIKE E'pg\\\\_%%'",
3789 "CURRENT_SCHEMA");
3790 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA", MatchAny) && (!ends_with(prev_wd, ',')))
3791 COMPLETE_WITH("WITH (");
3792 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
3793 else if (Matches("CREATE", "PUBLICATION", MatchAnyN, "WITH", "("))
3794 COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root");
3795
3796/* CREATE RULE */
3797 /* Complete "CREATE [ OR REPLACE ] RULE <sth>" with "AS ON" */
3798 else if (Matches("CREATE", "RULE", MatchAny) ||
3799 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny))
3800 COMPLETE_WITH("AS ON");
3801 /* Complete "CREATE [ OR REPLACE ] RULE <sth> AS" with "ON" */
3802 else if (Matches("CREATE", "RULE", MatchAny, "AS") ||
3803 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS"))
3804 COMPLETE_WITH("ON");
3805
3806 /*
3807 * Complete "CREATE [ OR REPLACE ] RULE <sth> AS ON" with
3808 * SELECT|UPDATE|INSERT|DELETE
3809 */
3810 else if (Matches("CREATE", "RULE", MatchAny, "AS", "ON") ||
3811 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS", "ON"))
3812 COMPLETE_WITH("SELECT", "UPDATE", "INSERT", "DELETE");
3813 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
3814 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
3815 COMPLETE_WITH("TO");
3816 /* Complete "AS ON <sth> TO" with a table name */
3817 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
3819
3820/* CREATE SCHEMA [ <name> ] [ AUTHORIZATION ] */
3821 else if (Matches("CREATE", "SCHEMA"))
3823 "AUTHORIZATION");
3824 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION") ||
3825 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION"))
3828 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION", MatchAny) ||
3829 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION", MatchAny))
3830 COMPLETE_WITH("CREATE", "GRANT");
3831 else if (Matches("CREATE", "SCHEMA", MatchAny))
3832 COMPLETE_WITH("AUTHORIZATION", "CREATE", "GRANT");
3833
3834/* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3835 else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
3836 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
3837 COMPLETE_WITH("AS", "INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
3838 "CACHE", "CYCLE", "OWNED BY", "START WITH");
3839 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "AS") ||
3840 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "AS"))
3841 COMPLETE_WITH_CS("smallint", "integer", "bigint");
3842 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "NO") ||
3843 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
3844 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
3845
3846/* CREATE SERVER <name> */
3847 else if (Matches("CREATE", "SERVER", MatchAny))
3848 COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
3849
3850/* CREATE STATISTICS <name> */
3851 else if (Matches("CREATE", "STATISTICS", MatchAny))
3852 COMPLETE_WITH("(", "ON");
3853 else if (Matches("CREATE", "STATISTICS", MatchAny, "("))
3854 COMPLETE_WITH("ndistinct", "dependencies", "mcv");
3855 else if (Matches("CREATE", "STATISTICS", MatchAny, "(*)"))
3856 COMPLETE_WITH("ON");
3857 else if (Matches("CREATE", "STATISTICS", MatchAny, MatchAnyN, "FROM"))
3859
3860/* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3861 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
3862 else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
3863 COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW");
3864 /* Complete "CREATE UNLOGGED" with TABLE or SEQUENCE */
3865 else if (TailMatches("CREATE", "UNLOGGED"))
3866 COMPLETE_WITH("TABLE", "SEQUENCE");
3867 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
3868 else if (TailMatches("PARTITION", "BY"))
3869 COMPLETE_WITH("RANGE (", "LIST (", "HASH (");
3870 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
3871 else if (TailMatches("PARTITION", "OF"))
3873 /* Limited completion support for partition bound specification */
3874 else if (TailMatches("PARTITION", "OF", MatchAny))
3875 COMPLETE_WITH("FOR VALUES", "DEFAULT");
3876 /* Complete CREATE TABLE <name> with '(', AS, OF or PARTITION OF */
3877 else if (TailMatches("CREATE", "TABLE", MatchAny) ||
3878 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny))
3879 COMPLETE_WITH("(", "AS", "OF", "PARTITION OF");
3880 /* Complete CREATE TABLE <name> OF with list of composite types */
3881 else if (TailMatches("CREATE", "TABLE", MatchAny, "OF") ||
3882 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "OF"))
3884 /* Complete CREATE TABLE <name> [ (...) ] AS with list of keywords */
3885 else if (TailMatches("CREATE", "TABLE", MatchAny, "AS") ||
3886 TailMatches("CREATE", "TABLE", MatchAny, "(*)", "AS") ||
3887 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "AS") ||
3888 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "AS"))
3889 COMPLETE_WITH("EXECUTE", "SELECT", "TABLE", "VALUES", "WITH");
3890 /* Complete CREATE TABLE name (...) with supported options */
3891 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)"))
3892 COMPLETE_WITH("AS", "INHERITS (", "PARTITION BY", "USING", "TABLESPACE", "WITH (");
3893 else if (TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)"))
3894 COMPLETE_WITH("AS", "INHERITS (", "USING", "TABLESPACE", "WITH (");
3895 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)"))
3896 COMPLETE_WITH("AS", "INHERITS (", "ON COMMIT", "PARTITION BY", "USING",
3897 "TABLESPACE", "WITH (");
3898 /* Complete CREATE TABLE (...) USING with table access methods */
3899 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "USING") ||
3900 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "USING"))
3902 /* Complete CREATE TABLE (...) WITH with storage parameters */
3903 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "WITH", "(") ||
3904 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "WITH", "("))
3906 /* Complete CREATE TABLE ON COMMIT with actions */
3907 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)", "ON", "COMMIT"))
3908 COMPLETE_WITH("DELETE ROWS", "DROP", "PRESERVE ROWS");
3909
3910/* CREATE TABLESPACE */
3911 else if (Matches("CREATE", "TABLESPACE", MatchAny))
3912 COMPLETE_WITH("OWNER", "LOCATION");
3913 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
3914 else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
3915 COMPLETE_WITH("LOCATION");
3916
3917/* CREATE TEXT SEARCH --- is allowed inside CREATE SCHEMA, so use TailMatches */
3918 else if (TailMatches("CREATE", "TEXT", "SEARCH"))
3919 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3920 else if (TailMatches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
3921 COMPLETE_WITH("(");
3922
3923/* CREATE TRANSFORM */
3924 else if (Matches("CREATE", "TRANSFORM") ||
3925 Matches("CREATE", "OR", "REPLACE", "TRANSFORM"))
3926 COMPLETE_WITH("FOR");
3927 else if (Matches("CREATE", "TRANSFORM", "FOR") ||
3928 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR"))
3930 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny) ||
3931 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny))
3932 COMPLETE_WITH("LANGUAGE");
3933 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE") ||
3934 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3935 {
3938 }
3939
3940/* CREATE SUBSCRIPTION */
3941 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny))
3942 COMPLETE_WITH("CONNECTION", "SERVER");
3943 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER"))
3945 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER", MatchAny))
3946 COMPLETE_WITH("PUBLICATION");
3947 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
3948 COMPLETE_WITH("PUBLICATION");
3949 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "SERVER",
3950 MatchAny, "PUBLICATION"))
3951 {
3952 /* complete with nothing here as this refers to remote publications */
3953 }
3954 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
3955 MatchAny, "PUBLICATION"))
3956 {
3957 /* complete with nothing here as this refers to remote publications */
3958 }
3959 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "PUBLICATION", MatchAny))
3960 COMPLETE_WITH("WITH (");
3961 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
3962 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "WITH", "("))
3963 COMPLETE_WITH("binary", "connect", "copy_data", "create_slot",
3964 "disable_on_error", "enabled", "failover",
3965 "max_retention_duration", "origin",
3966 "password_required", "retain_dead_tuples",
3967 "run_as_owner", "slot_name", "streaming",
3968 "synchronous_commit", "two_phase");
3969
3970/* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
3971
3972 /*
3973 * Complete CREATE [ OR REPLACE ] TRIGGER <name> with BEFORE|AFTER|INSTEAD
3974 * OF.
3975 */
3976 else if (TailMatches("CREATE", "TRIGGER", MatchAny) ||
3977 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny))
3978 COMPLETE_WITH("BEFORE", "AFTER", "INSTEAD OF");
3979
3980 /*
3981 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER with an
3982 * event.
3983 */
3984 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER") ||
3985 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
3986 COMPLETE_WITH("INSERT", "DELETE", "UPDATE", "TRUNCATE");
3987 /* Complete CREATE [ OR REPLACE ] TRIGGER <name> INSTEAD OF with an event */
3988 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF") ||
3989 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
3990 COMPLETE_WITH("INSERT", "DELETE", "UPDATE");
3991
3992 /*
3993 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER sth with
3994 * OR|ON.
3995 */
3996 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3997 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3998 TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny) ||
3999 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
4000 COMPLETE_WITH("ON", "OR");
4001
4002 /*
4003 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER event ON
4004 * with a list of tables. EXECUTE FUNCTION is the recommended grammar
4005 * instead of EXECUTE PROCEDURE in version 11 and upwards.
4006 */
4007 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON") ||
4008 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
4010
4011 /*
4012 * Complete CREATE [ OR REPLACE ] TRIGGER ... INSTEAD OF event ON with a
4013 * list of views.
4014 */
4015 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON") ||
4016 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
4018 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4019 "ON", MatchAny) ||
4020 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4021 "ON", MatchAny))
4022 {
4023 if (pset.sversion >= 110000)
4024 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
4025 "REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
4026 else
4027 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
4028 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4029 }
4030 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4031 "DEFERRABLE") ||
4032 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4033 "DEFERRABLE") ||
4034 Matches("CREATE", "TRIGGER", MatchAnyN,
4035 "INITIALLY", "IMMEDIATE|DEFERRED") ||
4036 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4037 "INITIALLY", "IMMEDIATE|DEFERRED"))
4038 {
4039 if (pset.sversion >= 110000)
4040 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
4041 else
4042 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4043 }
4044 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4045 "REFERENCING") ||
4046 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4047 "REFERENCING"))
4048 COMPLETE_WITH("OLD TABLE", "NEW TABLE");
4049 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4050 "OLD|NEW", "TABLE") ||
4051 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4052 "OLD|NEW", "TABLE"))
4053 COMPLETE_WITH("AS");
4054 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4055 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
4056 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4057 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
4058 Matches("CREATE", "TRIGGER", MatchAnyN,
4059 "REFERENCING", "OLD", "TABLE", MatchAny) ||
4060 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4061 "REFERENCING", "OLD", "TABLE", MatchAny))
4062 {
4063 if (pset.sversion >= 110000)
4064 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
4065 else
4066 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4067 }
4068 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4069 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
4070 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4071 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
4072 Matches("CREATE", "TRIGGER", MatchAnyN,
4073 "REFERENCING", "NEW", "TABLE", MatchAny) ||
4074 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4075 "REFERENCING", "NEW", "TABLE", MatchAny))
4076 {
4077 if (pset.sversion >= 110000)
4078 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
4079 else
4080 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
4081 }
4082 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4083 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4084 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4085 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4086 Matches("CREATE", "TRIGGER", MatchAnyN,
4087 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4088 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4089 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
4090 Matches("CREATE", "TRIGGER", MatchAnyN,
4091 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4092 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4093 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4094 Matches("CREATE", "TRIGGER", MatchAnyN,
4095 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
4096 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4097 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny))
4098 {
4099 if (pset.sversion >= 110000)
4100 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE FUNCTION");
4101 else
4102 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE PROCEDURE");
4103 }
4104 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4105 "FOR") ||
4106 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4107 "FOR"))
4108 COMPLETE_WITH("EACH", "ROW", "STATEMENT");
4109 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4110 "FOR", "EACH") ||
4111 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4112 "FOR", "EACH"))
4113 COMPLETE_WITH("ROW", "STATEMENT");
4114 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4115 "FOR", "EACH", "ROW|STATEMENT") ||
4116 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4117 "FOR", "EACH", "ROW|STATEMENT") ||
4118 Matches("CREATE", "TRIGGER", MatchAnyN,
4119 "FOR", "ROW|STATEMENT") ||
4120 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4121 "FOR", "ROW|STATEMENT"))
4122 {
4123 if (pset.sversion >= 110000)
4124 COMPLETE_WITH("WHEN (", "EXECUTE FUNCTION");
4125 else
4126 COMPLETE_WITH("WHEN (", "EXECUTE PROCEDURE");
4127 }
4128 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4129 "WHEN", "(*)") ||
4130 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4131 "WHEN", "(*)"))
4132 {
4133 if (pset.sversion >= 110000)
4134 COMPLETE_WITH("EXECUTE FUNCTION");
4135 else
4136 COMPLETE_WITH("EXECUTE PROCEDURE");
4137 }
4138
4139 /*
4140 * Complete CREATE [ OR REPLACE ] TRIGGER ... EXECUTE with
4141 * PROCEDURE|FUNCTION.
4142 */
4143 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4144 "EXECUTE") ||
4145 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4146 "EXECUTE"))
4147 {
4148 if (pset.sversion >= 110000)
4149 COMPLETE_WITH("FUNCTION");
4150 else
4151 COMPLETE_WITH("PROCEDURE");
4152 }
4153 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
4154 "EXECUTE", "FUNCTION|PROCEDURE") ||
4155 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
4156 "EXECUTE", "FUNCTION|PROCEDURE"))
4158
4159/* CREATE ROLE,USER,GROUP <name> */
4160 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny) &&
4161 !TailMatches("USER", "MAPPING"))
4162 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
4163 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
4164 "LOGIN", "NOBYPASSRLS",
4165 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
4166 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
4167 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
4168 "VALID UNTIL", "WITH");
4169
4170/* CREATE ROLE,USER,GROUP <name> WITH */
4171 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
4172 /* Similar to the above, but don't complete "WITH" again. */
4173 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
4174 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
4175 "LOGIN", "NOBYPASSRLS",
4176 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
4177 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
4178 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
4179 "VALID UNTIL");
4180
4181 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
4182 else if (Matches("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
4183 COMPLETE_WITH("GROUP", "ROLE");
4184
4185/* CREATE TYPE */
4186 else if (Matches("CREATE", "TYPE", MatchAny))
4187 COMPLETE_WITH("(", "AS");
4188 else if (Matches("CREATE", "TYPE", MatchAny, "AS"))
4189 COMPLETE_WITH("ENUM", "RANGE", "(");
4190 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "("))
4191 {
4192 if (TailMatches("(|*,", MatchAny))
4194 else if (TailMatches("(|*,", MatchAny, MatchAnyExcept("*)")))
4195 COMPLETE_WITH("COLLATE", ",", ")");
4196 }
4197 else if (Matches("CREATE", "TYPE", MatchAny, "AS", "ENUM|RANGE"))
4198 COMPLETE_WITH("(");
4199 else if (HeadMatches("CREATE", "TYPE", MatchAny, "("))
4200 {
4201 if (TailMatches("(|*,"))
4202 COMPLETE_WITH("INPUT", "OUTPUT", "RECEIVE", "SEND",
4203 "TYPMOD_IN", "TYPMOD_OUT", "ANALYZE", "SUBSCRIPT",
4204 "INTERNALLENGTH", "PASSEDBYVALUE", "ALIGNMENT",
4205 "STORAGE", "LIKE", "CATEGORY", "PREFERRED",
4206 "DEFAULT", "ELEMENT", "DELIMITER",
4207 "COLLATABLE");
4208 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
4209 COMPLETE_WITH("=");
4210 else if (TailMatches("=", MatchAnyExcept("*)")))
4211 COMPLETE_WITH(",", ")");
4212 }
4213 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "RANGE", "("))
4214 {
4215 if (TailMatches("(|*,"))
4216 COMPLETE_WITH("SUBTYPE", "SUBTYPE_OPCLASS", "COLLATION",
4217 "CANONICAL", "SUBTYPE_DIFF",
4218 "MULTIRANGE_TYPE_NAME");
4219 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
4220 COMPLETE_WITH("=");
4221 else if (TailMatches("=", MatchAnyExcept("*)")))
4222 COMPLETE_WITH(",", ")");
4223 }
4224
4225/* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
4226 /* Complete CREATE [ OR REPLACE ] VIEW <name> with AS or WITH */
4227 else if (TailMatches("CREATE", "VIEW", MatchAny) ||
4228 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny))
4229 COMPLETE_WITH("AS", "WITH");
4230 /* Complete "CREATE [ OR REPLACE ] VIEW <sth> AS with "SELECT" */
4231 else if (TailMatches("CREATE", "VIEW", MatchAny, "AS") ||
4232 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "AS"))
4233 COMPLETE_WITH("SELECT");
4234 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( yyy [= zzz] ) */
4235 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH") ||
4236 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH"))
4237 COMPLETE_WITH("(");
4238 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(") ||
4239 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "("))
4241 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option") ||
4242 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option"))
4243 COMPLETE_WITH("=");
4244 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option", "=") ||
4245 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option", "="))
4246 COMPLETE_WITH("local", "cascaded");
4247 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS */
4248 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)") ||
4249 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)"))
4250 COMPLETE_WITH("AS");
4251 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS SELECT */
4252 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)", "AS") ||
4253 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)", "AS"))
4254 COMPLETE_WITH("SELECT");
4255
4256/* CREATE MATERIALIZED VIEW */
4257 else if (Matches("CREATE", "MATERIALIZED"))
4258 COMPLETE_WITH("VIEW");
4259 /* Complete CREATE MATERIALIZED VIEW <name> with AS or USING */
4260 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
4261 COMPLETE_WITH("AS", "USING");
4262
4263 /*
4264 * Complete CREATE MATERIALIZED VIEW <name> USING with list of access
4265 * methods
4266 */
4267 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING"))
4269 /* Complete CREATE MATERIALIZED VIEW <name> USING <access method> with AS */
4270 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny))
4271 COMPLETE_WITH("AS");
4272
4273 /*
4274 * Complete CREATE MATERIALIZED VIEW <name> [USING <access method> ] AS
4275 * with "SELECT"
4276 */
4277 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS") ||
4278 Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS"))
4279 COMPLETE_WITH("SELECT");
4280
4281/* CREATE EVENT TRIGGER */
4282 else if (Matches("CREATE", "EVENT"))
4283 COMPLETE_WITH("TRIGGER");
4284 /* Complete CREATE EVENT TRIGGER <name> with ON */
4285 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny))
4286 COMPLETE_WITH("ON");
4287 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
4288 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
4289 COMPLETE_WITH("ddl_command_start", "ddl_command_end", "login",
4290 "sql_drop", "table_rewrite");
4291
4292 /*
4293 * Complete CREATE EVENT TRIGGER <name> ON <event_type>. EXECUTE FUNCTION
4294 * is the recommended grammar instead of EXECUTE PROCEDURE in version 11
4295 * and upwards.
4296 */
4297 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON", MatchAny))
4298 {
4299 if (pset.sversion >= 110000)
4300 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE FUNCTION");
4301 else
4302 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE PROCEDURE");
4303 }
4304 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "WHEN|AND", MatchAny, "IN", "(*)"))
4305 {
4306 if (pset.sversion >= 110000)
4307 COMPLETE_WITH("EXECUTE FUNCTION");
4308 else
4309 COMPLETE_WITH("EXECUTE PROCEDURE");
4310 }
4311 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "EXECUTE", "FUNCTION|PROCEDURE"))
4313
4314/* DEALLOCATE */
4315 else if (Matches("DEALLOCATE"))
4317 "ALL");
4318
4319/* DECLARE */
4320
4321 /*
4322 * Complete DECLARE <name> with one of BINARY, ASENSITIVE, INSENSITIVE,
4323 * SCROLL, NO SCROLL, and CURSOR.
4324 */
4325 else if (Matches("DECLARE", MatchAny))
4326 COMPLETE_WITH("BINARY", "ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL",
4327 "CURSOR");
4328
4329 /*
4330 * Complete DECLARE ... <option> with other options. The PostgreSQL parser
4331 * allows DECLARE options to be specified in any order. But the
4332 * tab-completion follows the ordering of them that the SQL standard
4333 * provides, like the syntax of DECLARE command in the documentation
4334 * indicates.
4335 */
4336 else if (Matches("DECLARE", MatchAnyN, "BINARY"))
4337 COMPLETE_WITH("ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR");
4338 else if (Matches("DECLARE", MatchAnyN, "ASENSITIVE|INSENSITIVE"))
4339 COMPLETE_WITH("SCROLL", "NO SCROLL", "CURSOR");
4340 else if (Matches("DECLARE", MatchAnyN, "SCROLL"))
4341 COMPLETE_WITH("CURSOR");
4342 /* Complete DECLARE ... [options] NO with SCROLL */
4343 else if (Matches("DECLARE", MatchAnyN, "NO"))
4344 COMPLETE_WITH("SCROLL");
4345
4346 /*
4347 * Complete DECLARE ... CURSOR with one of WITH HOLD, WITHOUT HOLD, and
4348 * FOR
4349 */
4350 else if (Matches("DECLARE", MatchAnyN, "CURSOR"))
4351 COMPLETE_WITH("WITH HOLD", "WITHOUT HOLD", "FOR");
4352 /* Complete DECLARE ... CURSOR WITH|WITHOUT with HOLD */
4353 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT"))
4354 COMPLETE_WITH("HOLD");
4355 /* Complete DECLARE ... CURSOR WITH|WITHOUT HOLD with FOR */
4356 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT", "HOLD"))
4357 COMPLETE_WITH("FOR");
4358
4359/* DELETE --- can be inside EXPLAIN, RULE, etc */
4360 /* Complete DELETE with "FROM" */
4361 else if (Matches("DELETE"))
4362 COMPLETE_WITH("FROM");
4363 /* Complete DELETE FROM with a list of tables */
4364 else if (TailMatches("DELETE", "FROM"))
4366 /* Complete DELETE FROM <table> */
4367 else if (TailMatches("DELETE", "FROM", MatchAny))
4368 COMPLETE_WITH("FOR", "USING", "WHERE");
4369 /* Complete DELETE FROM <table> FOR with PORTION */
4370 else if (TailMatches("DELETE", "FROM", MatchAny, "FOR"))
4371 COMPLETE_WITH("PORTION");
4372 /* Complete DELETE FROM <table> FOR PORTION with OF */
4373 else if (TailMatches("DELETE", "FROM", MatchAny, "FOR", "PORTION"))
4374 COMPLETE_WITH("OF");
4375 /* Complete DELETE FROM <table> FOR PORTION OF with column names */
4376 else if (TailMatches("DELETE", "FROM", MatchAny, "FOR", "PORTION", "OF"))
4378 /* Complete DELETE FROM <table> FOR PORTION OF <period> with FROM */
4379 else if (TailMatches("DELETE", "FROM", MatchAny, "FOR", "PORTION", "OF", MatchAny))
4380 COMPLETE_WITH("FROM");
4381 /* Complete DELETE FROM <table> USING with relations supporting SELECT */
4382 else if (TailMatches("DELETE", "FROM", MatchAny, "USING"))
4384
4385/* DISCARD */
4386 else if (Matches("DISCARD"))
4387 COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP");
4388
4389/* DO */
4390 else if (Matches("DO"))
4391 COMPLETE_WITH("LANGUAGE");
4392
4393/* DROP */
4394 /* Complete DROP object with CASCADE / RESTRICT */
4395 else if (Matches("DROP",
4396 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
4397 MatchAny) ||
4398 Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
4399 Matches("DROP", "EVENT", "TRIGGER", MatchAny) ||
4400 Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4401 Matches("DROP", "FOREIGN", "TABLE", MatchAny) ||
4402 Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
4403 COMPLETE_WITH("CASCADE", "RESTRICT");
4404 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
4405 ends_with(prev_wd, ')'))
4406 COMPLETE_WITH("CASCADE", "RESTRICT");
4407
4408 /* help completing some of the variants */
4409 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
4410 COMPLETE_WITH("(");
4411 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
4413 else if (Matches("DROP", "FOREIGN"))
4414 COMPLETE_WITH("DATA WRAPPER", "TABLE");
4415 else if (Matches("DROP", "DATABASE", MatchAny))
4416 COMPLETE_WITH("WITH (");
4417 else if (HeadMatches("DROP", "DATABASE") && (ends_with(prev_wd, '(')))
4418 COMPLETE_WITH("FORCE");
4419
4420 /* DROP INDEX */
4421 else if (Matches("DROP", "INDEX"))
4423 "CONCURRENTLY");
4424 else if (Matches("DROP", "INDEX", "CONCURRENTLY"))
4426 else if (Matches("DROP", "INDEX", MatchAny))
4427 COMPLETE_WITH("CASCADE", "RESTRICT");
4428 else if (Matches("DROP", "INDEX", "CONCURRENTLY", MatchAny))
4429 COMPLETE_WITH("CASCADE", "RESTRICT");
4430
4431 /* DROP MATERIALIZED VIEW */
4432 else if (Matches("DROP", "MATERIALIZED"))
4433 COMPLETE_WITH("VIEW");
4434 else if (Matches("DROP", "MATERIALIZED", "VIEW"))
4436 else if (Matches("DROP", "MATERIALIZED", "VIEW", MatchAny))
4437 COMPLETE_WITH("CASCADE", "RESTRICT");
4438
4439 /* DROP OWNED BY */
4440 else if (Matches("DROP", "OWNED"))
4441 COMPLETE_WITH("BY");
4442 else if (Matches("DROP", "OWNED", "BY"))
4444 else if (Matches("DROP", "OWNED", "BY", MatchAny))
4445 COMPLETE_WITH("CASCADE", "RESTRICT");
4446
4447 /* DROP TEXT SEARCH */
4448 else if (Matches("DROP", "TEXT", "SEARCH"))
4449 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
4450
4451 /* DROP TRIGGER */
4452 else if (Matches("DROP", "TRIGGER", MatchAny))
4453 COMPLETE_WITH("ON");
4454 else if (Matches("DROP", "TRIGGER", MatchAny, "ON"))
4455 {
4458 }
4459 else if (Matches("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
4460 COMPLETE_WITH("CASCADE", "RESTRICT");
4461
4462 /* DROP ACCESS METHOD */
4463 else if (Matches("DROP", "ACCESS"))
4464 COMPLETE_WITH("METHOD");
4465 else if (Matches("DROP", "ACCESS", "METHOD"))
4467
4468 /* DROP EVENT TRIGGER */
4469 else if (Matches("DROP", "EVENT"))
4470 COMPLETE_WITH("TRIGGER");
4471 else if (Matches("DROP", "EVENT", "TRIGGER"))
4473
4474 /* DROP POLICY <name> */
4475 else if (Matches("DROP", "POLICY"))
4477 /* DROP POLICY <name> ON */
4478 else if (Matches("DROP", "POLICY", MatchAny))
4479 COMPLETE_WITH("ON");
4480 /* DROP POLICY <name> ON <table> */
4481 else if (Matches("DROP", "POLICY", MatchAny, "ON"))
4482 {
4485 }
4486 else if (Matches("DROP", "POLICY", MatchAny, "ON", MatchAny))
4487 COMPLETE_WITH("CASCADE", "RESTRICT");
4488
4489 /* DROP PROPERTY GRAPH */
4490 else if (Matches("DROP", "PROPERTY"))
4491 COMPLETE_WITH("GRAPH");
4492 else if (Matches("DROP", "PROPERTY", "GRAPH"))
4494
4495 /* DROP RULE */
4496 else if (Matches("DROP", "RULE", MatchAny))
4497 COMPLETE_WITH("ON");
4498 else if (Matches("DROP", "RULE", MatchAny, "ON"))
4499 {
4502 }
4503 else if (Matches("DROP", "RULE", MatchAny, "ON", MatchAny))
4504 COMPLETE_WITH("CASCADE", "RESTRICT");
4505
4506 /* DROP TRANSFORM */
4507 else if (Matches("DROP", "TRANSFORM"))
4508 COMPLETE_WITH("FOR");
4509 else if (Matches("DROP", "TRANSFORM", "FOR"))
4511 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny))
4512 COMPLETE_WITH("LANGUAGE");
4513 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
4514 {
4517 }
4518 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE", MatchAny))
4519 COMPLETE_WITH("CASCADE", "RESTRICT");
4520
4521/* EXECUTE */
4522 else if (Matches("EXECUTE"))
4524
4525/*
4526 * EXPLAIN [ ( option [, ...] ) ] statement
4527 * EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
4528 */
4529 else if (Matches("EXPLAIN"))
4530 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4531 "MERGE INTO", "EXECUTE", "ANALYZE", "VERBOSE");
4532 else if (HeadMatches("EXPLAIN", "(*") &&
4533 !HeadMatches("EXPLAIN", "(*)"))
4534 {
4535 /*
4536 * This fires if we're in an unfinished parenthesized option list.
4537 * get_previous_words treats a completed parenthesized option list as
4538 * one word, so the above test is correct.
4539 */
4540 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
4541 COMPLETE_WITH("ANALYZE", "VERBOSE", "COSTS", "SETTINGS", "GENERIC_PLAN",
4542 "BUFFERS", "SERIALIZE", "WAL", "TIMING", "SUMMARY",
4543 "MEMORY", "IO", "FORMAT");
4544 else if (TailMatches("ANALYZE|VERBOSE|COSTS|SETTINGS|GENERIC_PLAN|BUFFERS|WAL|TIMING|SUMMARY|MEMORY|IO"))
4545 COMPLETE_WITH("ON", "OFF");
4546 else if (TailMatches("SERIALIZE"))
4547 COMPLETE_WITH("TEXT", "NONE", "BINARY");
4548 else if (TailMatches("FORMAT"))
4549 COMPLETE_WITH("TEXT", "XML", "JSON", "YAML");
4550 }
4551 else if (Matches("EXPLAIN", "ANALYZE"))
4552 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4553 "MERGE INTO", "EXECUTE", "VERBOSE");
4554 else if (Matches("EXPLAIN", "(*)") ||
4555 Matches("EXPLAIN", "VERBOSE") ||
4556 Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
4557 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4558 "MERGE INTO", "EXECUTE");
4559
4560/* FETCH && MOVE */
4561
4562 /*
4563 * Complete FETCH with one of ABSOLUTE, BACKWARD, FORWARD, RELATIVE, ALL,
4564 * NEXT, PRIOR, FIRST, LAST, FROM, IN, and a list of cursors
4565 */
4566 else if (Matches("FETCH|MOVE"))
4568 "ABSOLUTE",
4569 "BACKWARD",
4570 "FORWARD",
4571 "RELATIVE",
4572 "ALL",
4573 "NEXT",
4574 "PRIOR",
4575 "FIRST",
4576 "LAST",
4577 "FROM",
4578 "IN");
4579
4580 /*
4581 * Complete FETCH BACKWARD or FORWARD with one of ALL, FROM, IN, and a
4582 * list of cursors
4583 */
4584 else if (Matches("FETCH|MOVE", "BACKWARD|FORWARD"))
4586 "ALL",
4587 "FROM",
4588 "IN");
4589
4590 /*
4591 * Complete FETCH <direction> with "FROM" or "IN". These are equivalent,
4592 * but we may as well tab-complete both: perhaps some users prefer one
4593 * variant or the other.
4594 */
4595 else if (Matches("FETCH|MOVE", "ABSOLUTE|BACKWARD|FORWARD|RELATIVE",
4596 MatchAnyExcept("FROM|IN")) ||
4597 Matches("FETCH|MOVE", "ALL|NEXT|PRIOR|FIRST|LAST"))
4599 "FROM",
4600 "IN");
4601 /* Complete FETCH <direction> "FROM" or "IN" with a list of cursors */
4602 else if (Matches("FETCH|MOVE", MatchAnyN, "FROM|IN"))
4604
4605/* FOREIGN DATA WRAPPER */
4606 /* applies in ALTER/DROP FDW and in CREATE SERVER */
4607 else if (TailMatches("FOREIGN", "DATA", "WRAPPER") &&
4608 !TailMatches("CREATE", MatchAny, MatchAny, MatchAny))
4610 /* applies in CREATE SERVER */
4611 else if (Matches("CREATE", "SERVER", MatchAnyN, "FOREIGN", "DATA", "WRAPPER", MatchAny))
4612 COMPLETE_WITH("OPTIONS");
4613
4614/* FOREIGN TABLE */
4615 else if (TailMatches("FOREIGN", "TABLE") &&
4616 !TailMatches("CREATE", MatchAny, MatchAny))
4618
4619/* FOREIGN SERVER */
4620 else if (TailMatches("FOREIGN", "SERVER"))
4622
4623/*
4624 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
4625 * ALTER DEFAULT PRIVILEGES, so use TailMatches
4626 */
4627 /* Complete GRANT/REVOKE with a list of roles and privileges */
4628 else if (TailMatches("GRANT|REVOKE") ||
4629 TailMatches("REVOKE", "ADMIN|GRANT|INHERIT|SET", "OPTION", "FOR"))
4630 {
4631 /*
4632 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
4633 * privileges (can't grant roles)
4634 */
4635 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4636 {
4637 if (TailMatches("GRANT") ||
4638 TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4639 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4640 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4641 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL");
4642 else if (TailMatches("REVOKE"))
4643 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4644 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4645 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL",
4646 "GRANT OPTION FOR");
4647 }
4648 else if (TailMatches("GRANT"))
4651 else if (TailMatches("REVOKE"))
4654 "GRANT OPTION FOR",
4655 "ADMIN OPTION FOR",
4656 "INHERIT OPTION FOR",
4657 "SET OPTION FOR");
4658 else if (TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4660 else if (TailMatches("REVOKE", "ADMIN|INHERIT|SET", "OPTION", "FOR"))
4662 }
4663
4664 else if (TailMatches("GRANT|REVOKE", "ALTER") ||
4665 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER"))
4666 COMPLETE_WITH("SYSTEM");
4667
4668 else if (TailMatches("REVOKE", "SET"))
4669 COMPLETE_WITH("ON PARAMETER", "OPTION FOR");
4670 else if (TailMatches("GRANT", "SET") ||
4671 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "SET") ||
4672 TailMatches("GRANT|REVOKE", "ALTER", "SYSTEM") ||
4673 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER", "SYSTEM"))
4674 COMPLETE_WITH("ON PARAMETER");
4675
4676 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "PARAMETER") ||
4677 TailMatches("GRANT|REVOKE", MatchAny, MatchAny, "ON", "PARAMETER") ||
4678 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER") ||
4679 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER"))
4681
4682 else if (TailMatches("GRANT", MatchAny, "ON", "PARAMETER", MatchAny) ||
4683 TailMatches("GRANT", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4684 COMPLETE_WITH("TO");
4685
4686 else if (TailMatches("REVOKE", MatchAny, "ON", "PARAMETER", MatchAny) ||
4687 TailMatches("REVOKE", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny) ||
4688 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER", MatchAny) ||
4689 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4690 COMPLETE_WITH("FROM");
4691
4692 /*
4693 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
4694 * TO/FROM
4695 */
4696 else if (TailMatches("GRANT|REVOKE", MatchAny) ||
4697 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny))
4698 {
4699 if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|MAINTAIN|ALL"))
4700 COMPLETE_WITH("ON");
4701 else if (TailMatches("GRANT", MatchAny))
4702 COMPLETE_WITH("TO");
4703 else
4704 COMPLETE_WITH("FROM");
4705 }
4706
4707 /*
4708 * Complete GRANT/REVOKE <sth> ON with a list of appropriate relations.
4709 *
4710 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
4711 * here will only work if the privilege list contains exactly one
4712 * privilege.
4713 */
4714 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON") ||
4715 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON"))
4716 {
4717 /*
4718 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
4719 * objects supported.
4720 */
4721 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4722 COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS", "LARGE OBJECTS");
4723 else
4725 "ALL FUNCTIONS IN SCHEMA",
4726 "ALL PROCEDURES IN SCHEMA",
4727 "ALL ROUTINES IN SCHEMA",
4728 "ALL SEQUENCES IN SCHEMA",
4729 "ALL TABLES IN SCHEMA",
4730 "DATABASE",
4731 "DOMAIN",
4732 "FOREIGN DATA WRAPPER",
4733 "FOREIGN SERVER",
4734 "FUNCTION",
4735 "LANGUAGE",
4736 "LARGE OBJECT",
4737 "PARAMETER",
4738 "PROCEDURE",
4739 "PROPERTY GRAPH",
4740 "ROUTINE",
4741 "SCHEMA",
4742 "SEQUENCE",
4743 "TABLE",
4744 "TABLESPACE",
4745 "TYPE");
4746 }
4747 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
4748 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
4749 COMPLETE_WITH("FUNCTIONS IN SCHEMA",
4750 "PROCEDURES IN SCHEMA",
4751 "ROUTINES IN SCHEMA",
4752 "SEQUENCES IN SCHEMA",
4753 "TABLES IN SCHEMA");
4754
4755 /*
4756 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
4757 * appropriate objects or keywords.
4758 *
4759 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
4760 */
4761 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny) ||
4762 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny))
4763 {
4764 if (TailMatches("DATABASE"))
4766 else if (TailMatches("DOMAIN"))
4768 else if (TailMatches("FUNCTION"))
4770 else if (TailMatches("FOREIGN"))
4771 COMPLETE_WITH("DATA WRAPPER", "SERVER");
4772 else if (TailMatches("LANGUAGE"))
4774 else if (TailMatches("LARGE"))
4775 {
4776 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4777 COMPLETE_WITH("OBJECTS");
4778 else
4779 COMPLETE_WITH("OBJECT");
4780 }
4781 else if (TailMatches("PROCEDURE"))
4783 else if (TailMatches("ROUTINE"))
4785 else if (TailMatches("SCHEMA"))
4787 else if (TailMatches("SEQUENCE"))
4789 else if (TailMatches("TABLE"))
4791 else if (TailMatches("TABLESPACE"))
4793 else if (TailMatches("TYPE"))
4795 else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
4796 COMPLETE_WITH("TO");
4797 else
4798 COMPLETE_WITH("FROM");
4799 }
4800
4801 /*
4802 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
4803 * CURRENT_ROLE, CURRENT_USER, or SESSION_USER.
4804 */
4805 else if (Matches("GRANT", MatchAnyN, "TO") ||
4806 Matches("REVOKE", MatchAnyN, "FROM"))
4809
4810 /*
4811 * Offer grant options after that.
4812 */
4813 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny))
4814 COMPLETE_WITH("WITH ADMIN",
4815 "WITH INHERIT",
4816 "WITH SET",
4817 "WITH GRANT OPTION",
4818 "GRANTED BY");
4819 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH"))
4820 COMPLETE_WITH("ADMIN",
4821 "INHERIT",
4822 "SET",
4823 "GRANT OPTION");
4824 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", "ADMIN|INHERIT|SET"))
4825 COMPLETE_WITH("OPTION", "TRUE", "FALSE");
4826 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION"))
4827 COMPLETE_WITH("GRANTED BY");
4828 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY"))
4831 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
4832 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO|FROM"))
4835 /* Offer WITH GRANT OPTION after that */
4836 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO", MatchAny))
4837 COMPLETE_WITH("WITH GRANT OPTION");
4838 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
4839 else if (Matches("GRANT|REVOKE", MatchAnyN, "ON", MatchAny, MatchAny) &&
4840 !TailMatches("FOREIGN", "SERVER") && !TailMatches("LARGE", "OBJECT"))
4841 {
4842 if (Matches("GRANT", MatchAnyN, "ON", MatchAny, MatchAny))
4843 COMPLETE_WITH("TO");
4844 else
4845 COMPLETE_WITH("FROM");
4846 }
4847
4848 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
4849 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
4850 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
4851 {
4853 COMPLETE_WITH("TO");
4854 else
4855 COMPLETE_WITH("FROM");
4856 }
4857
4858 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
4859 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4860 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
4861 {
4863 COMPLETE_WITH("TO");
4864 else
4865 COMPLETE_WITH("FROM");
4866 }
4867
4868 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
4869 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
4870 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
4871 {
4873 COMPLETE_WITH("TO");
4874 else
4875 COMPLETE_WITH("FROM");
4876 }
4877
4878 /* Complete "GRANT/REVOKE * ON LARGE OBJECT *" with TO/FROM */
4879 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "LARGE", "OBJECT", MatchAny) ||
4880 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "LARGE", "OBJECT", MatchAny))
4881 {
4883 COMPLETE_WITH("TO");
4884 else
4885 COMPLETE_WITH("FROM");
4886 }
4887
4888 /* Complete "GRANT/REVOKE * ON LARGE OBJECTS" with TO/FROM */
4889 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "LARGE", "OBJECTS") ||
4890 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "LARGE", "OBJECTS"))
4891 {
4893 COMPLETE_WITH("TO");
4894 else
4895 COMPLETE_WITH("FROM");
4896 }
4897
4898/* GRAPH_TABLE */
4899 else if (TailMatches("GRAPH_TABLE"))
4900 COMPLETE_WITH("(");
4901 else if (TailMatches("GRAPH_TABLE", "("))
4903 else if (TailMatches("GRAPH_TABLE", "(", MatchAny))
4904 COMPLETE_WITH("MATCH");
4905
4906/* GROUP BY */
4907 else if (TailMatches("FROM", MatchAny, "GROUP"))
4908 COMPLETE_WITH("BY");
4909
4910/* IMPORT FOREIGN SCHEMA */
4911 else if (Matches("IMPORT"))
4912 COMPLETE_WITH("FOREIGN SCHEMA");
4913 else if (Matches("IMPORT", "FOREIGN"))
4914 COMPLETE_WITH("SCHEMA");
4915 else if (Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny))
4916 COMPLETE_WITH("EXCEPT (", "FROM SERVER", "LIMIT TO (");
4917 else if (TailMatches("LIMIT", "TO", "(*)") ||
4918 Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny, "EXCEPT", "(*)"))
4919 COMPLETE_WITH("FROM SERVER");
4920 else if (TailMatches("FROM", "SERVER", MatchAny))
4921 COMPLETE_WITH("INTO");
4922 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO"))
4924 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO", MatchAny))
4925 COMPLETE_WITH("OPTIONS (");
4926
4927/* INSERT --- can be inside EXPLAIN, RULE, etc */
4928 /* Complete NOT MATCHED THEN INSERT */
4929 else if (TailMatches("NOT", "MATCHED", "THEN", "INSERT"))
4930 COMPLETE_WITH("VALUES", "(");
4931 /* Complete INSERT with "INTO" */
4932 else if (TailMatches("INSERT"))
4933 COMPLETE_WITH("INTO");
4934 /* Complete INSERT INTO with table names */
4935 else if (TailMatches("INSERT", "INTO"))
4937 /* Complete "INSERT INTO <table> (" with attribute names */
4938 else if (TailMatches("INSERT", "INTO", MatchAny, "("))
4940
4941 /*
4942 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
4943 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
4944 */
4945 else if (TailMatches("INSERT", "INTO", MatchAny))
4946 COMPLETE_WITH("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
4947
4948 /*
4949 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
4950 * "TABLE" or "OVERRIDING"
4951 */
4952 else if (TailMatches("INSERT", "INTO", MatchAny, MatchAny) &&
4953 ends_with(prev_wd, ')'))
4954 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "OVERRIDING");
4955
4956 /* Complete OVERRIDING */
4957 else if (TailMatches("OVERRIDING"))
4958 COMPLETE_WITH("SYSTEM VALUE", "USER VALUE");
4959
4960 /* Complete after OVERRIDING clause */
4961 else if (TailMatches("OVERRIDING", MatchAny, "VALUE"))
4962 COMPLETE_WITH("SELECT", "TABLE", "VALUES");
4963
4964 /* Insert an open parenthesis after "VALUES" */
4965 else if (TailMatches("VALUES") && !TailMatches("DEFAULT", "VALUES"))
4966 COMPLETE_WITH("(");
4967
4968/* LOCK */
4969 /* Complete LOCK [TABLE] [ONLY] with a list of tables */
4970 else if (Matches("LOCK"))
4972 "TABLE", "ONLY");
4973 else if (Matches("LOCK", "TABLE"))
4975 "ONLY");
4976 else if (Matches("LOCK", "TABLE", "ONLY") || Matches("LOCK", "ONLY"))
4978 /* For the following, handle the case of a single table only for now */
4979
4980 /* Complete LOCK [TABLE] [ONLY] <table> with IN or NOWAIT */
4981 else if (Matches("LOCK", MatchAnyExcept("TABLE|ONLY")) ||
4982 Matches("LOCK", "TABLE", MatchAnyExcept("ONLY")) ||
4983 Matches("LOCK", "ONLY", MatchAny) ||
4984 Matches("LOCK", "TABLE", "ONLY", MatchAny))
4985 COMPLETE_WITH("IN", "NOWAIT");
4986
4987 /* Complete LOCK [TABLE] [ONLY] <table> IN with a lock mode */
4988 else if (Matches("LOCK", MatchAnyN, "IN"))
4989 COMPLETE_WITH("ACCESS SHARE MODE",
4990 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
4991 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
4992 "SHARE ROW EXCLUSIVE MODE",
4993 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
4994
4995 /*
4996 * Complete LOCK [TABLE][ONLY] <table> IN ACCESS|ROW with rest of lock
4997 * mode
4998 */
4999 else if (Matches("LOCK", MatchAnyN, "IN", "ACCESS|ROW"))
5000 COMPLETE_WITH("EXCLUSIVE MODE", "SHARE MODE");
5001
5002 /* Complete LOCK [TABLE] [ONLY] <table> IN SHARE with rest of lock mode */
5003 else if (Matches("LOCK", MatchAnyN, "IN", "SHARE"))
5004 COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE",
5005 "UPDATE EXCLUSIVE MODE");
5006
5007 /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with "NOWAIT" */
5008 else if (Matches("LOCK", MatchAnyN, "MODE"))
5009 COMPLETE_WITH("NOWAIT");
5010
5011/* MERGE --- can be inside EXPLAIN */
5012 else if (TailMatches("MERGE"))
5013 COMPLETE_WITH("INTO");
5014 else if (TailMatches("MERGE", "INTO"))
5016
5017 /* Complete MERGE INTO <table> [[AS] <alias>] with USING */
5018 else if (TailMatches("MERGE", "INTO", MatchAny))
5019 COMPLETE_WITH("USING", "AS");
5020 else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
5021 TailMatches("MERGE", "INTO", MatchAny, MatchAnyExcept("USING|AS")))
5022 COMPLETE_WITH("USING");
5023
5024 /*
5025 * Complete MERGE INTO ... USING with a list of relations supporting
5026 * SELECT
5027 */
5028 else if (TailMatches("MERGE", "INTO", MatchAny, "USING") ||
5029 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING") ||
5030 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING"))
5032
5033 /*
5034 * Complete MERGE INTO <table> [[AS] <alias>] USING <relations> [[AS]
5035 * alias] with ON
5036 */
5037 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny) ||
5038 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny) ||
5039 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny))
5040 COMPLETE_WITH("AS", "ON");
5041 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5042 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5043 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, "AS", MatchAny) ||
5044 TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
5045 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
5046 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")))
5047 COMPLETE_WITH("ON");
5048
5049 /* Complete MERGE INTO ... ON with target table attributes */
5050 else if (TailMatches("INTO", MatchAny, "USING", MatchAny, "ON"))
5052 else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny, "ON"))
5054 else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAny, "ON"))
5056
5057 /*
5058 * Complete ... USING <relation> [[AS] alias] ON join condition
5059 * (consisting of one or three words typically used) with WHEN [NOT]
5060 * MATCHED
5061 */
5062 else if (TailMatches("USING", MatchAny, "ON", MatchAny) ||
5063 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny) ||
5064 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny) ||
5065 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
5066 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
5067 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")))
5068 COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
5069 else if (TailMatches("USING", MatchAny, "ON", MatchAny, "WHEN") ||
5070 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, "WHEN") ||
5071 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, "WHEN") ||
5072 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
5073 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
5074 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN"))
5075 COMPLETE_WITH("MATCHED", "NOT MATCHED");
5076
5077 /*
5078 * Complete ... WHEN MATCHED and WHEN NOT MATCHED BY SOURCE|TARGET with
5079 * THEN/AND
5080 */
5081 else if (TailMatches("WHEN", "MATCHED") ||
5082 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE|TARGET"))
5083 COMPLETE_WITH("THEN", "AND");
5084
5085 /* Complete ... WHEN NOT MATCHED with BY/THEN/AND */
5086 else if (TailMatches("WHEN", "NOT", "MATCHED"))
5087 COMPLETE_WITH("BY", "THEN", "AND");
5088
5089 /* Complete ... WHEN NOT MATCHED BY with SOURCE/TARGET */
5090 else if (TailMatches("WHEN", "NOT", "MATCHED", "BY"))
5091 COMPLETE_WITH("SOURCE", "TARGET");
5092
5093 /*
5094 * Complete ... WHEN MATCHED THEN and WHEN NOT MATCHED BY SOURCE THEN with
5095 * UPDATE SET/DELETE/DO NOTHING
5096 */
5097 else if (TailMatches("WHEN", "MATCHED", "THEN") ||
5098 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE", "THEN"))
5099 COMPLETE_WITH("UPDATE SET", "DELETE", "DO NOTHING");
5100
5101 /*
5102 * Complete ... WHEN NOT MATCHED [BY TARGET] THEN with INSERT/DO NOTHING
5103 */
5104 else if (TailMatches("WHEN", "NOT", "MATCHED", "THEN") ||
5105 TailMatches("WHEN", "NOT", "MATCHED", "BY", "TARGET", "THEN"))
5106 COMPLETE_WITH("INSERT", "DO NOTHING");
5107
5108/* NOTIFY --- can be inside EXPLAIN, RULE, etc */
5109 else if (TailMatches("NOTIFY"))
5111
5112/* OPTIONS */
5113 else if (TailMatches("OPTIONS"))
5114 COMPLETE_WITH("(");
5115
5116/* OWNER TO - complete with available roles */
5117 else if (TailMatches("OWNER", "TO"))
5120
5121/* ORDER BY */
5122 else if (TailMatches("FROM", MatchAny, "ORDER"))
5123 COMPLETE_WITH("BY");
5124 else if (TailMatches("FROM", MatchAny, "ORDER", "BY"))
5126
5127/* PREPARE xx AS */
5128 else if (Matches("PREPARE", MatchAny, "AS"))
5129 COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM",
5130 "MERGE INTO", "VALUES", "WITH", "TABLE");
5131
5132/*
5133 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
5134 * managers, not for manual use in interactive sessions.
5135 */
5136
5137/* REASSIGN OWNED BY xxx TO yyy */
5138 else if (Matches("REASSIGN"))
5139 COMPLETE_WITH("OWNED BY");
5140 else if (Matches("REASSIGN", "OWNED"))
5141 COMPLETE_WITH("BY");
5142 else if (Matches("REASSIGN", "OWNED", "BY"))
5144 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny))
5145 COMPLETE_WITH("TO");
5146 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
5148
5149/* REFRESH MATERIALIZED VIEW */
5150 else if (Matches("REFRESH"))
5151 COMPLETE_WITH("MATERIALIZED VIEW");
5152 else if (Matches("REFRESH", "MATERIALIZED"))
5153 COMPLETE_WITH("VIEW");
5154 else if (Matches("REFRESH", "MATERIALIZED", "VIEW"))
5156 "CONCURRENTLY");
5157 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
5159 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
5160 COMPLETE_WITH("WITH");
5161 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
5162 COMPLETE_WITH("WITH");
5163 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
5164 COMPLETE_WITH("NO DATA", "DATA");
5165 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
5166 COMPLETE_WITH("NO DATA", "DATA");
5167 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
5168 COMPLETE_WITH("DATA");
5169 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
5170 COMPLETE_WITH("DATA");
5171
5172/* REINDEX */
5173 else if (Matches("REINDEX") ||
5174 Matches("REINDEX", "(*)"))
5175 COMPLETE_WITH("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
5176 else if (Matches("REINDEX", "TABLE") ||
5177 Matches("REINDEX", "(*)", "TABLE"))
5179 "CONCURRENTLY");
5180 else if (Matches("REINDEX", "INDEX") ||
5181 Matches("REINDEX", "(*)", "INDEX"))
5183 "CONCURRENTLY");
5184 else if (Matches("REINDEX", "SCHEMA") ||
5185 Matches("REINDEX", "(*)", "SCHEMA"))
5187 "CONCURRENTLY");
5188 else if (Matches("REINDEX", "SYSTEM|DATABASE") ||
5189 Matches("REINDEX", "(*)", "SYSTEM|DATABASE"))
5191 "CONCURRENTLY");
5192 else if (Matches("REINDEX", "TABLE", "CONCURRENTLY") ||
5193 Matches("REINDEX", "(*)", "TABLE", "CONCURRENTLY"))
5195 else if (Matches("REINDEX", "INDEX", "CONCURRENTLY") ||
5196 Matches("REINDEX", "(*)", "INDEX", "CONCURRENTLY"))
5198 else if (Matches("REINDEX", "SCHEMA", "CONCURRENTLY") ||
5199 Matches("REINDEX", "(*)", "SCHEMA", "CONCURRENTLY"))
5201 else if (Matches("REINDEX", "SYSTEM|DATABASE", "CONCURRENTLY") ||
5202 Matches("REINDEX", "(*)", "SYSTEM|DATABASE", "CONCURRENTLY"))
5204 else if (HeadMatches("REINDEX", "(*") &&
5205 !HeadMatches("REINDEX", "(*)"))
5206 {
5207 /*
5208 * This fires if we're in an unfinished parenthesized option list.
5209 * get_previous_words treats a completed parenthesized option list as
5210 * one word, so the above test is correct.
5211 */
5212 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5213 COMPLETE_WITH("CONCURRENTLY", "TABLESPACE", "VERBOSE");
5214 else if (TailMatches("TABLESPACE"))
5216 }
5217
5218/* REPACK */
5219 else if (Matches("REPACK"))
5221 "(", "USING INDEX");
5222 else if (Matches("REPACK", "(*)"))
5224 "USING INDEX");
5225 else if (Matches("REPACK", MatchAnyExcept("(")))
5226 COMPLETE_WITH("USING INDEX");
5227 else if (Matches("REPACK", "(*)", MatchAnyExcept("(")))
5228 COMPLETE_WITH("USING INDEX");
5229 else if (Matches("REPACK", MatchAny, "USING", "INDEX") ||
5230 Matches("REPACK", "(*)", MatchAny, "USING", "INDEX"))
5231 {
5234 }
5235
5236 /*
5237 * Complete ... [ (*) ] <sth> USING INDEX, with a list of indexes for
5238 * <sth>.
5239 */
5240 else if (TailMatches(MatchAny, "USING", "INDEX"))
5241 {
5244 }
5245 else if (HeadMatches("REPACK", "(*") &&
5246 !HeadMatches("REPACK", "(*)"))
5247 {
5248 /*
5249 * This fires if we're in an unfinished parenthesized option list.
5250 * get_previous_words treats a completed parenthesized option list as
5251 * one word, so the above test is correct.
5252 */
5253 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5254 COMPLETE_WITH("ANALYZE", "CONCURRENTLY", "VERBOSE");
5255 else if (TailMatches("ANALYZE|CONCURRENTLY|VERBOSE"))
5256 COMPLETE_WITH("ON", "OFF");
5257 }
5258
5259/* SECURITY LABEL */
5260 else if (Matches("SECURITY"))
5261 COMPLETE_WITH("LABEL");
5262 else if (Matches("SECURITY", "LABEL"))
5263 COMPLETE_WITH("ON", "FOR");
5264 else if (Matches("SECURITY", "LABEL", "FOR", MatchAny))
5265 COMPLETE_WITH("ON");
5266 else if (Matches("SECURITY", "LABEL", "ON") ||
5267 Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
5268 COMPLETE_WITH("TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
5269 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION",
5270 "LARGE OBJECT", "MATERIALIZED VIEW", "LANGUAGE",
5271 "PROPERTY GRAPH", "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
5272 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW");
5273 else if (Matches("SECURITY", "LABEL", "ON", "PROPERTY", "GRAPH"))
5275 else if (Matches("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
5276 COMPLETE_WITH("IS");
5277
5278/* SELECT */
5279 /* naah . . . */
5280
5281/* SET, RESET, SHOW */
5282 /* Complete with a variable name */
5283 else if (TailMatches("SET|RESET") &&
5284 !TailMatches("UPDATE", MatchAny, "SET") &&
5285 !TailMatches("ALTER", "DATABASE|USER|ROLE", MatchAny, "RESET"))
5287 "CONSTRAINTS",
5288 "TRANSACTION",
5289 "SESSION",
5290 "ROLE",
5291 "TABLESPACE",
5292 "ALL");
5293 else if (Matches("SHOW"))
5295 "SESSION AUTHORIZATION",
5296 "ALL");
5297 else if (Matches("SHOW", "SESSION"))
5298 COMPLETE_WITH("AUTHORIZATION");
5299 /* Complete "SET TRANSACTION" */
5300 else if (Matches("SET", "TRANSACTION"))
5301 COMPLETE_WITH("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
5302 else if (Matches("BEGIN|START", "TRANSACTION") ||
5303 Matches("BEGIN", "WORK") ||
5304 Matches("BEGIN") ||
5305 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
5306 COMPLETE_WITH("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
5307 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
5308 Matches("BEGIN", "NOT") ||
5309 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
5310 COMPLETE_WITH("DEFERRABLE");
5311 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
5312 Matches("BEGIN", "ISOLATION") ||
5313 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
5314 COMPLETE_WITH("LEVEL");
5315 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
5316 Matches("BEGIN", "ISOLATION", "LEVEL") ||
5317 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
5318 COMPLETE_WITH("READ", "REPEATABLE READ", "SERIALIZABLE");
5319 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
5320 Matches("BEGIN", "ISOLATION", "LEVEL", "READ") ||
5321 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
5322 COMPLETE_WITH("UNCOMMITTED", "COMMITTED");
5323 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
5324 Matches("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
5325 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
5326 COMPLETE_WITH("READ");
5327 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
5328 Matches("BEGIN", "READ") ||
5329 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
5330 COMPLETE_WITH("ONLY", "WRITE");
5331 /* SET CONSTRAINTS */
5332 else if (Matches("SET", "CONSTRAINTS"))
5334 "ALL");
5335 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
5336 else if (Matches("SET", "CONSTRAINTS", MatchAny))
5337 COMPLETE_WITH("DEFERRED", "IMMEDIATE");
5338 /* Complete SET ROLE */
5339 else if (Matches("SET", "ROLE"))
5341 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
5342 else if (Matches("SET", "SESSION"))
5343 COMPLETE_WITH("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
5344 /* Complete SET SESSION AUTHORIZATION with username */
5345 else if (Matches("SET", "SESSION", "AUTHORIZATION"))
5347 "DEFAULT");
5348 /* Complete RESET SESSION with AUTHORIZATION */
5349 else if (Matches("RESET", "SESSION"))
5350 COMPLETE_WITH("AUTHORIZATION");
5351 /* Complete SET <var> with "TO" */
5352 else if (Matches("SET", MatchAny))
5353 COMPLETE_WITH("TO");
5354
5355 /*
5356 * Complete ALTER DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER ... SET
5357 * <name>
5358 */
5359 else if (Matches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER", MatchAnyN, "SET", MatchAnyExcept("SCHEMA")))
5360 COMPLETE_WITH("FROM CURRENT", "TO");
5361
5362 /*
5363 * Suggest possible variable values in SET variable TO|=, along with the
5364 * preceding ALTER syntaxes.
5365 */
5366 else if (TailMatches("SET", MatchAny, "TO|=") &&
5367 !TailMatches("UPDATE", MatchAny, "SET", MatchAny, "TO|="))
5368 {
5369 /* special cased code for individual GUCs */
5370 if (TailMatches("DateStyle", "TO|="))
5371 COMPLETE_WITH("ISO", "SQL", "Postgres", "German",
5372 "YMD", "DMY", "MDY",
5373 "US", "European", "NonEuropean",
5374 "DEFAULT");
5375 else if (TailMatches("search_path", "TO|="))
5376 {
5377 /* Here, we want to allow pg_catalog, so use narrower exclusion */
5379 " AND nspname NOT LIKE E'pg\\\\_toast%%'"
5380 " AND nspname NOT LIKE E'pg\\\\_temp%%'",
5381 "DEFAULT");
5382 }
5383 else if (TailMatches("TimeZone", "TO|="))
5385 else
5386 {
5387 /* generic, type based, GUC support */
5388 char *guctype = get_guctype(prev2_wd);
5389
5390 /*
5391 * Note: if we don't recognize the GUC name, it's important to not
5392 * offer any completions, as most likely we've misinterpreted the
5393 * context and this isn't a GUC-setting command at all.
5394 */
5395 if (guctype)
5396 {
5397 if (strcmp(guctype, "enum") == 0)
5398 {
5401 "DEFAULT");
5402 }
5403 else if (strcmp(guctype, "bool") == 0)
5404 COMPLETE_WITH("on", "off", "true", "false", "yes", "no",
5405 "1", "0", "DEFAULT");
5406 else
5407 COMPLETE_WITH("DEFAULT");
5408
5409 free(guctype);
5410 }
5411 }
5412 }
5413
5414/* START TRANSACTION */
5415 else if (Matches("START"))
5416 COMPLETE_WITH("TRANSACTION");
5417
5418/* TABLE, but not TABLE embedded in other commands */
5419 else if (Matches("TABLE"))
5421
5422/* TABLESAMPLE */
5423 else if (TailMatches("TABLESAMPLE"))
5425 else if (TailMatches("TABLESAMPLE", MatchAny))
5426 COMPLETE_WITH("(");
5427
5428/* TRUNCATE */
5429 else if (Matches("TRUNCATE"))
5431 "TABLE", "ONLY");
5432 else if (Matches("TRUNCATE", "TABLE"))
5434 "ONLY");
5435 else if (Matches("TRUNCATE", MatchAnyN, "ONLY"))
5437 else if (Matches("TRUNCATE", MatchAny) ||
5438 Matches("TRUNCATE", "TABLE|ONLY", MatchAny) ||
5439 Matches("TRUNCATE", "TABLE", "ONLY", MatchAny))
5440 COMPLETE_WITH("RESTART IDENTITY", "CONTINUE IDENTITY", "CASCADE", "RESTRICT");
5441 else if (Matches("TRUNCATE", MatchAnyN, "IDENTITY"))
5442 COMPLETE_WITH("CASCADE", "RESTRICT");
5443
5444/* UNLISTEN */
5445 else if (Matches("UNLISTEN"))
5447
5448/* UPDATE --- can be inside EXPLAIN, RULE, etc */
5449 /* If prev. word is UPDATE suggest a list of tables */
5450 else if (TailMatches("UPDATE"))
5452 /* Complete UPDATE <table> with "SET" or "FOR" (for FOR PORTION OF) */
5453 else if (TailMatches("UPDATE", MatchAny))
5454 COMPLETE_WITH("FOR", "SET");
5455 /* Complete UPDATE <table> FOR with PORTION */
5456 else if (TailMatches("UPDATE", MatchAny, "FOR"))
5457 COMPLETE_WITH("PORTION");
5458 /* Complete UPDATE <table> FOR PORTION with OF */
5459 else if (TailMatches("UPDATE", MatchAny, "FOR", "PORTION"))
5460 COMPLETE_WITH("OF");
5461 /* Complete UPDATE <table> FOR PORTION OF with column names */
5462 else if (TailMatches("UPDATE", MatchAny, "FOR", "PORTION", "OF"))
5464 /* Complete UPDATE <table> FOR PORTION OF <period> with FROM */
5465 else if (TailMatches("UPDATE", MatchAny, "FOR", "PORTION", "OF", MatchAny))
5466 COMPLETE_WITH("FROM");
5467 /* Complete UPDATE <table> SET with list of attributes */
5468 else if (TailMatches("UPDATE", MatchAny, "SET"))
5470 /* UPDATE <table> SET <attr> = */
5471 else if (TailMatches("UPDATE", MatchAny, "SET", MatchAnyExcept("*=")))
5472 COMPLETE_WITH("=");
5473
5474/* USER MAPPING */
5475 else if (Matches("ALTER|CREATE|DROP", "USER", "MAPPING"))
5476 COMPLETE_WITH("FOR");
5477 else if (Matches("CREATE", "USER", "MAPPING", "FOR"))
5479 "CURRENT_ROLE",
5480 "CURRENT_USER",
5481 "PUBLIC",
5482 "USER");
5483 else if (Matches("ALTER|DROP", "USER", "MAPPING", "FOR"))
5485 else if (Matches("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
5486 COMPLETE_WITH("SERVER");
5487 else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
5488 COMPLETE_WITH("OPTIONS");
5489
5490/*
5491 * VACUUM [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
5492 * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ [ ONLY ] table_and_columns [, ...] ]
5493 */
5494 else if (Matches("VACUUM"))
5496 "(",
5497 "FULL",
5498 "FREEZE",
5499 "VERBOSE",
5500 "ANALYZE",
5501 "ONLY");
5502 else if (HeadMatches("VACUUM", "(*") &&
5503 !HeadMatches("VACUUM", "(*)"))
5504 {
5505 /*
5506 * This fires if we're in an unfinished parenthesized option list.
5507 * get_previous_words treats a completed parenthesized option list as
5508 * one word, so the above test is correct.
5509 */
5510 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5511 COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
5512 "DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
5513 "INDEX_CLEANUP", "PROCESS_MAIN", "PROCESS_TOAST",
5514 "TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
5515 "ONLY_DATABASE_STATS", "BUFFER_USAGE_LIMIT");
5516 else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_MAIN|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
5517 COMPLETE_WITH("ON", "OFF");
5518 else if (TailMatches("INDEX_CLEANUP"))
5519 COMPLETE_WITH("AUTO", "ON", "OFF");
5520 }
5521 else if (Matches("VACUUM", "(*)"))
5523 "ONLY");
5524 else if (Matches("VACUUM", "FULL"))
5526 "FREEZE",
5527 "VERBOSE",
5528 "ANALYZE",
5529 "ONLY");
5530 else if (Matches("VACUUM", MatchAnyN, "FREEZE"))
5532 "VERBOSE",
5533 "ANALYZE",
5534 "ONLY");
5535 else if (Matches("VACUUM", MatchAnyN, "VERBOSE"))
5537 "ANALYZE",
5538 "ONLY");
5539 else if (Matches("VACUUM", MatchAnyN, "ANALYZE"))
5541 "ONLY");
5542 else if (Matches("VACUUM", MatchAnyN, "("))
5543 /* "VACUUM (" should be caught above, so assume we want columns */
5545 else if (HeadMatches("VACUUM"))
5547
5548/*
5549 * WAIT FOR LSN '<lsn>' [ WITH ( option [, ...] ) ]
5550 * where option can be:
5551 * MODE '<mode>'
5552 * TIMEOUT '<timeout>'
5553 * NO_THROW
5554 * and mode can be:
5555 * standby_replay | standby_write | standby_flush | primary_flush
5556 */
5557 else if (Matches("WAIT"))
5558 COMPLETE_WITH("FOR");
5559 else if (Matches("WAIT", "FOR"))
5560 COMPLETE_WITH("LSN");
5561 else if (Matches("WAIT", "FOR", "LSN"))
5562 /* No completion for LSN value - user must provide manually */
5563 ;
5564 else if (Matches("WAIT", "FOR", "LSN", MatchAny))
5565 COMPLETE_WITH("WITH");
5566 else if (Matches("WAIT", "FOR", "LSN", MatchAny, "WITH"))
5567 COMPLETE_WITH("(");
5568
5569 /*
5570 * Handle parenthesized option list. This fires when we're in an
5571 * unfinished parenthesized option list. get_previous_words treats a
5572 * completed parenthesized option list as one word, so the above test is
5573 * correct.
5574 *
5575 * 'mode' takes a string value (one of the listed above), 'timeout' takes
5576 * a string value, and 'no_throw' takes no value. We do not offer
5577 * completions for the *values* of 'timeout' or 'no_throw'.
5578 */
5579 else if (HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*") &&
5580 !HeadMatches("WAIT", "FOR", "LSN", MatchAny, "WITH", "(*)"))
5581 {
5582 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5583 COMPLETE_WITH("mode", "timeout", "no_throw");
5584 else if (TailMatches("mode"))
5585 COMPLETE_WITH("'standby_replay'", "'standby_write'", "'standby_flush'", "'primary_flush'");
5586 }
5587
5588/* WITH [RECURSIVE] */
5589
5590 /*
5591 * Only match when WITH is the first word, as WITH may appear in many
5592 * other contexts.
5593 */
5594 else if (Matches("WITH"))
5595 COMPLETE_WITH("RECURSIVE");
5596
5597/* WHERE */
5598 /* Simple case of the word before the where being the table name */
5599 else if (TailMatches(MatchAny, "WHERE"))
5601
5602/* ... FROM ... */
5603/* TODO: also include SRF ? */
5604 else if (TailMatches("FROM") && !Matches("COPY|\\copy", MatchAny, "FROM"))
5606
5607/* ... JOIN ... */
5608 else if (TailMatches("JOIN"))
5610 else if (TailMatches("JOIN", MatchAny) && !TailMatches("CROSS|NATURAL", "JOIN", MatchAny))
5611 COMPLETE_WITH("ON", "USING (");
5612 else if (TailMatches("JOIN", MatchAny, MatchAny) &&
5613 !TailMatches("CROSS|NATURAL", "JOIN", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5614 COMPLETE_WITH("ON", "USING (");
5615 else if (TailMatches("JOIN", "LATERAL", MatchAny, MatchAny) &&
5616 !TailMatches("CROSS|NATURAL", "JOIN", "LATERAL", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5617 COMPLETE_WITH("ON", "USING (");
5618 else if (TailMatches("JOIN", MatchAny, "USING") ||
5619 TailMatches("JOIN", MatchAny, MatchAny, "USING") ||
5620 TailMatches("JOIN", "LATERAL", MatchAny, MatchAny, "USING"))
5621 COMPLETE_WITH("(");
5622 else if (TailMatches("JOIN", MatchAny, "USING", "("))
5624 else if (TailMatches("JOIN", MatchAny, MatchAny, "USING", "("))
5626
5627/* ... AT [ LOCAL | TIME ZONE ] ... */
5628 else if (TailMatches("AT"))
5629 COMPLETE_WITH("LOCAL", "TIME ZONE");
5630 else if (TailMatches("AT", "TIME", "ZONE"))
5632
5633/* Backslash commands */
5634/* TODO: \dc \dd \dl */
5635 else if (TailMatchesCS("\\?"))
5636 COMPLETE_WITH_CS("commands", "options", "variables");
5637 else if (TailMatchesCS("\\connect|\\c"))
5638 {
5641 }
5642 else if (TailMatchesCS("\\connect|\\c", MatchAny))
5643 {
5646 }
5647 else if (TailMatchesCS("\\da*"))
5649 else if (TailMatchesCS("\\dAc*", MatchAny) ||
5650 TailMatchesCS("\\dAf*", MatchAny))
5652 else if (TailMatchesCS("\\dAo*", MatchAny) ||
5653 TailMatchesCS("\\dAp*", MatchAny))
5655 else if (TailMatchesCS("\\dA*"))
5657 else if (TailMatchesCS("\\db*"))
5659 else if (TailMatchesCS("\\dconfig*"))
5661 else if (TailMatchesCS("\\dD*"))
5663 else if (TailMatchesCS("\\des*"))
5665 else if (TailMatchesCS("\\deu*"))
5667 else if (TailMatchesCS("\\dew*"))
5669 else if (TailMatchesCS("\\df*"))
5671 else if (HeadMatchesCS("\\df*"))
5673
5674 else if (TailMatchesCS("\\dFd*"))
5676 else if (TailMatchesCS("\\dFp*"))
5678 else if (TailMatchesCS("\\dFt*"))
5680 /* must be at end of \dF alternatives: */
5681 else if (TailMatchesCS("\\dF*"))
5683
5684 else if (TailMatchesCS("\\di*"))
5686 else if (TailMatchesCS("\\dL*"))
5688 else if (TailMatchesCS("\\dn*"))
5690 /* no support for completing operators, but we can complete types: */
5691 else if (HeadMatchesCS("\\do*", MatchAny))
5693 else if (TailMatchesCS("\\dp") || TailMatchesCS("\\z"))
5695 else if (TailMatchesCS("\\dPi*"))
5697 else if (TailMatchesCS("\\dPt*"))
5699 else if (TailMatchesCS("\\dP*"))
5701 else if (TailMatchesCS("\\dRp*"))
5703 else if (TailMatchesCS("\\dRs*"))
5705 else if (TailMatchesCS("\\ds*"))
5707 else if (TailMatchesCS("\\dt*"))
5709 else if (TailMatchesCS("\\dT*"))
5711 else if (TailMatchesCS("\\du*") ||
5712 TailMatchesCS("\\dg*") ||
5713 TailMatchesCS("\\drg*"))
5715 else if (TailMatchesCS("\\dv*"))
5717 else if (TailMatchesCS("\\dx*"))
5719 else if (TailMatchesCS("\\dX*"))
5721 else if (TailMatchesCS("\\dm*"))
5723 else if (TailMatchesCS("\\dE*"))
5725 else if (TailMatchesCS("\\dy*"))
5727
5728 /* must be at end of \d alternatives: */
5729 else if (TailMatchesCS("\\d*"))
5731
5732 else if (TailMatchesCS("\\ef"))
5734 else if (TailMatchesCS("\\ev"))
5736
5737 else if (TailMatchesCS("\\encoding"))
5739 else if (TailMatchesCS("\\h|\\help"))
5741 else if (TailMatchesCS("\\h|\\help", MatchAny))
5742 {
5743 if (TailMatches("DROP"))
5745 else if (TailMatches("ALTER"))
5747
5748 /*
5749 * CREATE is recognized by tail match elsewhere, so doesn't need to be
5750 * repeated here
5751 */
5752 }
5753 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny))
5754 {
5755 if (TailMatches("CREATE|DROP", "ACCESS"))
5756 COMPLETE_WITH("METHOD");
5757 else if (TailMatches("ALTER", "DEFAULT"))
5758 COMPLETE_WITH("PRIVILEGES");
5759 else if (TailMatches("CREATE|ALTER|DROP", "EVENT"))
5760 COMPLETE_WITH("TRIGGER");
5761 else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN"))
5762 COMPLETE_WITH("DATA WRAPPER", "TABLE");
5763 else if (TailMatches("ALTER", "LARGE"))
5764 COMPLETE_WITH("OBJECT");
5765 else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED"))
5766 COMPLETE_WITH("VIEW");
5767 else if (TailMatches("CREATE|ALTER|DROP", "PROPERTY"))
5768 COMPLETE_WITH("GRAPH");
5769 else if (TailMatches("CREATE|ALTER|DROP", "TEXT"))
5770 COMPLETE_WITH("SEARCH");
5771 else if (TailMatches("CREATE|ALTER|DROP", "USER"))
5772 COMPLETE_WITH("MAPPING FOR");
5773 }
5774 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny))
5775 {
5776 if (TailMatches("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
5777 COMPLETE_WITH("WRAPPER");
5778 else if (TailMatches("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
5779 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
5780 else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING"))
5781 COMPLETE_WITH("FOR");
5782 }
5783 else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*"))
5785 else if (TailMatchesCS("\\password"))
5787 else if (TailMatchesCS("\\pset"))
5788 COMPLETE_WITH_CS("border", "columns", "csv_fieldsep",
5789 "display_false", "display_true", "expanded",
5790 "fieldsep", "fieldsep_zero", "footer", "format",
5791 "linestyle", "null", "numericlocale",
5792 "pager", "pager_min_lines",
5793 "recordsep", "recordsep_zero",
5794 "tableattr", "title", "tuples_only",
5795 "unicode_border_linestyle",
5796 "unicode_column_linestyle",
5797 "unicode_header_linestyle",
5798 "xheader_width");
5799 else if (TailMatchesCS("\\pset", MatchAny))
5800 {
5801 if (TailMatchesCS("format"))
5802 COMPLETE_WITH_CS("aligned", "asciidoc", "csv", "html", "latex",
5803 "latex-longtable", "troff-ms", "unaligned",
5804 "wrapped");
5805 else if (TailMatchesCS("xheader_width"))
5806 COMPLETE_WITH_CS("full", "column", "page");
5807 else if (TailMatchesCS("linestyle"))
5808 COMPLETE_WITH_CS("ascii", "old-ascii", "unicode");
5809 else if (TailMatchesCS("pager"))
5810 COMPLETE_WITH_CS("on", "off", "always");
5811 else if (TailMatchesCS("unicode_border_linestyle|"
5812 "unicode_column_linestyle|"
5813 "unicode_header_linestyle"))
5814 COMPLETE_WITH_CS("single", "double");
5815 }
5816 else if (TailMatchesCS("\\unset"))
5817 matches = complete_from_variables(text, "", "", true);
5818 else if (TailMatchesCS("\\set"))
5819 matches = complete_from_variables(text, "", "", false);
5820 else if (TailMatchesCS("\\set", MatchAny))
5821 {
5822 if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|SHOW_ALL_RESULTS|"
5823 "SINGLELINE|SINGLESTEP"))
5824 COMPLETE_WITH_CS("on", "off");
5825 else if (TailMatchesCS("COMP_KEYWORD_CASE"))
5826 COMPLETE_WITH_CS("lower", "upper",
5827 "preserve-lower", "preserve-upper");
5828 else if (TailMatchesCS("ECHO"))
5829 COMPLETE_WITH_CS("errors", "queries", "all", "none");
5830 else if (TailMatchesCS("ECHO_HIDDEN"))
5831 COMPLETE_WITH_CS("noexec", "off", "on");
5832 else if (TailMatchesCS("HISTCONTROL"))
5833 COMPLETE_WITH_CS("ignorespace", "ignoredups",
5834 "ignoreboth", "none");
5835 else if (TailMatchesCS("ON_ERROR_ROLLBACK"))
5836 COMPLETE_WITH_CS("on", "off", "interactive");
5837 else if (TailMatchesCS("SHOW_CONTEXT"))
5838 COMPLETE_WITH_CS("never", "errors", "always");
5839 else if (TailMatchesCS("VERBOSITY"))
5840 COMPLETE_WITH_CS("default", "verbose", "terse", "sqlstate");
5841 }
5842 else if (TailMatchesCS("\\sf*"))
5844 else if (TailMatchesCS("\\sv*"))
5846 else if (TailMatchesCS("\\cd|\\e|\\edit|\\g|\\gx|\\i|\\include|"
5847 "\\ir|\\include_relative|\\o|\\out|"
5848 "\\s|\\w|\\write|\\lo_import") ||
5849 TailMatchesCS("\\lo_export", MatchAny))
5850 COMPLETE_WITH_FILES("\\", false);
5851
5852 /* gen_tabcomplete.pl ends special processing here */
5853 /* END GEN_TABCOMPLETE */
5854
5855 return matches;
5856}
5857
5858
5859/*
5860 * GENERATOR FUNCTIONS
5861 *
5862 * These functions do all the actual work of completing the input. They get
5863 * passed the text so far and the count how many times they have been called
5864 * so far with the same text.
5865 * If you read the above carefully, you'll see that these don't get called
5866 * directly but through the readline interface.
5867 * The return value is expected to be the full completion of the text, going
5868 * through a list each time, or NULL if there are no more matches. The string
5869 * will be free()'d by readline, so you must run it through strdup() or
5870 * something of that sort.
5871 */
5872
5873/*
5874 * Common routine for create_command_generator and drop_command_generator.
5875 * Entries that have 'excluded' flags are not returned.
5876 */
5877static char *
5878create_or_drop_command_generator(const char *text, int state, uint32 excluded)
5879{
5880 static int list_index,
5881 string_length;
5882 const char *name;
5883
5884 /* If this is the first time for this completion, init some values */
5885 if (state == 0)
5886 {
5887 list_index = 0;
5888 string_length = strlen(text);
5889 }
5890
5891 /* find something that matches */
5892 while ((name = words_after_create[list_index++].name))
5893 {
5894 if ((pg_strncasecmp(name, text, string_length) == 0) &&
5895 !(words_after_create[list_index - 1].flags & excluded))
5897 }
5898 /* if nothing matches, return NULL */
5899 return NULL;
5900}
5901
5902/*
5903 * This one gives you one from a list of things you can put after CREATE
5904 * as defined above.
5905 */
5906static char *
5907create_command_generator(const char *text, int state)
5908{
5910}
5911
5912/*
5913 * This function gives you a list of things you can put after a DROP command.
5914 */
5915static char *
5916drop_command_generator(const char *text, int state)
5917{
5919}
5920
5921/*
5922 * This function gives you a list of things you can put after an ALTER command.
5923 */
5924static char *
5925alter_command_generator(const char *text, int state)
5926{
5928}
5929
5930/*
5931 * These functions generate lists using server queries.
5932 * They are all wrappers for _complete_from_query.
5933 */
5934
5935static char *
5936complete_from_query(const char *text, int state)
5937{
5938 /* query is assumed to work for any server version */
5941}
5942
5943static char *
5945{
5947
5948 /* Find appropriate array element */
5949 while (pset.sversion < vquery->min_server_version)
5950 vquery++;
5951 /* Fail completion if server is too old */
5952 if (vquery->query == NULL)
5953 return NULL;
5954
5957}
5958
5959static char *
5960complete_from_schema_query(const char *text, int state)
5961{
5962 /* query is assumed to work for any server version */
5965}
5966
5967static char *
5969{
5971
5972 /* Find appropriate array element */
5973 while (pset.sversion < squery->min_server_version)
5974 squery++;
5975 /* Fail completion if server is too old */
5976 if (squery->catname == NULL)
5977 return NULL;
5978
5981}
5982
5983
5984/*
5985 * This creates a list of matching things, according to a query described by
5986 * the initial arguments. The caller has already done any work needed to
5987 * select the appropriate query for the server's version.
5988 *
5989 * The query can be one of two kinds:
5990 *
5991 * 1. A simple query, which must contain a restriction clause of the form
5992 * output LIKE '%s'
5993 * where "output" is the same string that the query returns. The %s
5994 * will be replaced by a LIKE pattern to match the already-typed text.
5995 * There can be a second '%s', which will be replaced by a suitably-escaped
5996 * version of the string provided in completion_ref_object. If there is a
5997 * third '%s', it will be replaced by a suitably-escaped version of the string
5998 * provided in completion_ref_schema. Those strings should be set up
5999 * by calling set_completion_reference or set_completion_reference_verbatim.
6000 * Simple queries should return a single column of matches. If "verbatim"
6001 * is true, the matches are returned as-is; otherwise, they are taken to
6002 * be SQL identifiers and quoted if necessary.
6003 *
6004 * 2. A schema query used for completion of both schema and relation names.
6005 * This is represented by a SchemaQuery object; see that typedef for details.
6006 *
6007 * See top of file for examples of both kinds of query.
6008 *
6009 * In addition to the query itself, we accept a null-terminated array of
6010 * literal keywords, which will be returned if they match the input-so-far
6011 * (case insensitively). (These are in addition to keywords specified
6012 * within the schema_query, if any.)
6013 *
6014 * If "verbatim" is true, then we use the given text as-is to match the
6015 * query results; otherwise we parse it as a possibly-qualified identifier,
6016 * and reconstruct suitable quoting afterward.
6017 *
6018 * "text" and "state" are supplied by Readline. "text" is the word we are
6019 * trying to complete. "state" is zero on first call, nonzero later.
6020 *
6021 * readline will call this repeatedly with the same text and varying
6022 * state. On each call, we are supposed to return a malloc'd string
6023 * that is a candidate completion. Return NULL when done.
6024 */
6025static char *
6028 const char *const *keywords,
6029 bool verbatim,
6030 const char *text, int state)
6031{
6032 static int list_index,
6035 num_keywords;
6036 static PGresult *result = NULL;
6037 static bool non_empty_object;
6038 static bool schemaquoted;
6039 static bool objectquoted;
6040
6041 /*
6042 * If this is the first time for this completion, we fetch a list of our
6043 * "things" from the backend.
6044 */
6045 if (state == 0)
6046 {
6048 char *schemaname;
6049 char *objectname;
6050 char *e_object_like;
6051 char *e_schemaname;
6052 char *e_ref_object;
6053 char *e_ref_schema;
6054
6055 /* Reset static state, ensuring no memory leaks */
6056 list_index = 0;
6057 num_schema_only = 0;
6058 num_query_other = 0;
6059 num_keywords = 0;
6060 PQclear(result);
6061 result = NULL;
6062
6063 /* Parse text, splitting into schema and object name if needed */
6064 if (verbatim)
6065 {
6067 schemaname = NULL;
6068 }
6069 else
6070 {
6072 &schemaname, &objectname,
6074 }
6075
6076 /* Remember whether the user has typed anything in the object part */
6077 non_empty_object = (*objectname != '\0');
6078
6079 /*
6080 * Convert objectname to a LIKE prefix pattern (e.g. 'foo%'), and set
6081 * up suitably-escaped copies of all the strings we need.
6082 */
6084
6085 if (schemaname)
6086 e_schemaname = escape_string(schemaname);
6087 else
6089
6092 else
6094
6097 else
6099
6101
6102 if (schema_query)
6103 {
6105
6106 /*
6107 * We issue different queries depending on whether the input is
6108 * already qualified or not. schema_query gives us the pieces to
6109 * assemble.
6110 */
6111 if (schemaname == NULL || schema_query->namespace == NULL)
6112 {
6113 /* Get unqualified names matching the input-so-far */
6115 if (schema_query->use_distinct)
6116 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
6118 "%s, NULL::pg_catalog.text FROM %s",
6119 schema_query->result,
6120 schema_query->catname);
6121 if (schema_query->refnamespace && completion_ref_schema)
6123 ", pg_catalog.pg_namespace nr");
6125 if (schema_query->selcondition)
6126 appendPQExpBuffer(&query_buffer, "%s AND ",
6127 schema_query->selcondition);
6128 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s'",
6129 schema_query->result,
6131 if (schema_query->viscondition)
6132 appendPQExpBuffer(&query_buffer, " AND %s",
6133 schema_query->viscondition);
6134 if (schema_query->refname)
6135 {
6137 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
6138 schema_query->refname, e_ref_object);
6139 if (schema_query->refnamespace && completion_ref_schema)
6141 " AND %s = nr.oid AND nr.nspname = '%s'",
6142 schema_query->refnamespace,
6143 e_ref_schema);
6144 else if (schema_query->refviscondition)
6146 " AND %s",
6147 schema_query->refviscondition);
6148 }
6149
6150 /*
6151 * When fetching relation names, suppress system catalogs
6152 * unless the input-so-far begins with "pg_". This is a
6153 * compromise between not offering system catalogs for
6154 * completion at all, and having them swamp the result when
6155 * the input is just "p".
6156 */
6157 if (strcmp(schema_query->catname,
6158 "pg_catalog.pg_class c") == 0 &&
6159 strncmp(objectname, "pg_", 3) != 0)
6160 {
6162 " AND c.relnamespace <> (SELECT oid FROM"
6163 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
6164 }
6165
6166 /*
6167 * If the target object type can be schema-qualified, add in
6168 * schema names matching the input-so-far.
6169 */
6170 if (schema_query->namespace)
6171 {
6172 appendPQExpBuffer(&query_buffer, "\nUNION ALL\n"
6173 "SELECT NULL::pg_catalog.text, n.nspname "
6174 "FROM pg_catalog.pg_namespace n "
6175 "WHERE n.nspname LIKE '%s'",
6177
6178 /*
6179 * Likewise, suppress system schemas unless the
6180 * input-so-far begins with "pg_".
6181 */
6182 if (strncmp(objectname, "pg_", 3) != 0)
6184 " AND n.nspname NOT LIKE E'pg\\\\_%'");
6185
6186 /*
6187 * Since we're matching these schema names to the object
6188 * name, handle their quoting using the object name's
6189 * quoting state.
6190 */
6192 }
6193 }
6194 else
6195 {
6196 /* Input is qualified, so produce only qualified names */
6198 if (schema_query->use_distinct)
6199 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
6200 appendPQExpBuffer(&query_buffer, "%s, n.nspname "
6201 "FROM %s, pg_catalog.pg_namespace n",
6202 schema_query->result,
6203 schema_query->catname);
6204 if (schema_query->refnamespace && completion_ref_schema)
6206 ", pg_catalog.pg_namespace nr");
6207 appendPQExpBuffer(&query_buffer, " WHERE %s = n.oid AND ",
6208 schema_query->namespace);
6209 if (schema_query->selcondition)
6210 appendPQExpBuffer(&query_buffer, "%s AND ",
6211 schema_query->selcondition);
6212 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s' AND ",
6213 schema_query->result,
6215 appendPQExpBuffer(&query_buffer, "n.nspname = '%s'",
6216 e_schemaname);
6217 if (schema_query->refname)
6218 {
6220 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
6221 schema_query->refname, e_ref_object);
6222 if (schema_query->refnamespace && completion_ref_schema)
6224 " AND %s = nr.oid AND nr.nspname = '%s'",
6225 schema_query->refnamespace,
6226 e_ref_schema);
6227 else if (schema_query->refviscondition)
6229 " AND %s",
6230 schema_query->refviscondition);
6231 }
6232 }
6233 }
6234 else
6235 {
6237 /* simple_query is an sprintf-style format string */
6241 }
6242
6243 /* Limit the number of records in the result */
6244 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
6246
6247 /* Finally, we can issue the query */
6249
6250 /* Clean up */
6252 free(schemaname);
6258 }
6259
6260 /* Return the next result, if any, but not if the query failed */
6262 {
6263 int nskip;
6264
6265 while (list_index < PQntuples(result))
6266 {
6267 const char *item = NULL;
6268 const char *nsp = NULL;
6269
6270 if (!PQgetisnull(result, list_index, 0))
6271 item = PQgetvalue(result, list_index, 0);
6272 if (PQnfields(result) > 1 &&
6273 !PQgetisnull(result, list_index, 1))
6274 nsp = PQgetvalue(result, list_index, 1);
6275 list_index++;
6276
6277 /* In verbatim mode, we return all the items as-is */
6278 if (verbatim)
6279 {
6281 return pg_strdup(item);
6282 }
6283
6284 /*
6285 * In normal mode, a name requiring quoting will be returned only
6286 * if the input was empty or quoted. Otherwise the user might see
6287 * completion inserting a quote she didn't type, which is
6288 * surprising. This restriction also dodges some odd behaviors of
6289 * some versions of readline/libedit.
6290 */
6291 if (non_empty_object)
6292 {
6293 if (item && !objectquoted && identifier_needs_quotes(item))
6294 continue;
6296 continue;
6297 }
6298
6299 /* Count schema-only results for hack below */
6300 if (item == NULL && nsp != NULL)
6302 else
6304
6306 }
6307
6308 /*
6309 * When the query result is exhausted, check for hard-wired keywords.
6310 * These will only be returned if they match the input-so-far,
6311 * ignoring case.
6312 */
6313 nskip = list_index - PQntuples(result);
6314 if (schema_query && schema_query->keywords)
6315 {
6316 const char *const *itemp = schema_query->keywords;
6317
6318 while (*itemp)
6319 {
6320 const char *item = *itemp++;
6321
6322 if (nskip-- > 0)
6323 continue;
6324 list_index++;
6325 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6326 {
6327 num_keywords++;
6328 return pg_strdup_keyword_case(item, text);
6329 }
6330 }
6331 }
6332 if (keywords)
6333 {
6334 const char *const *itemp = keywords;
6335
6336 while (*itemp)
6337 {
6338 const char *item = *itemp++;
6339
6340 if (nskip-- > 0)
6341 continue;
6342 list_index++;
6343 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6344 {
6345 num_keywords++;
6346 return pg_strdup_keyword_case(item, text);
6347 }
6348 }
6349 }
6350 }
6351
6352 /*
6353 * Hack: if we returned only bare schema names, don't let Readline add a
6354 * space afterwards. Otherwise the schema will stop being part of the
6355 * completion subject text, which is not what we want.
6356 */
6357 if (num_schema_only > 0 && num_query_other == 0 && num_keywords == 0)
6359
6360 /* No more matches, so free the result structure and return null */
6361 PQclear(result);
6362 result = NULL;
6363 return NULL;
6364}
6365
6366
6367/*
6368 * Set up completion_ref_object and completion_ref_schema
6369 * by parsing the given word. These variables can then be
6370 * used in a query passed to _complete_from_query.
6371 */
6372static void
6373set_completion_reference(const char *word)
6374{
6375 bool schemaquoted,
6377
6381}
6382
6383/*
6384 * Set up completion_ref_object when it should just be
6385 * the given word verbatim.
6386 */
6387static void
6389{
6392}
6393
6394
6395/*
6396 * This function returns in order one of a fixed, NULL pointer terminated list
6397 * of strings (if matching). This can be used if there are only a fixed number
6398 * SQL words that can appear at certain spot.
6399 */
6400static char *
6401complete_from_list(const char *text, int state)
6402{
6403 static int string_length,
6404 list_index,
6405 matches;
6406 static bool casesensitive;
6407 const char *item;
6408
6409 /* need to have a list */
6411
6412 /* Initialization */
6413 if (state == 0)
6414 {
6415 list_index = 0;
6416 string_length = strlen(text);
6418 matches = 0;
6419 }
6420
6421 while ((item = completion_charpp[list_index++]))
6422 {
6423 /* First pass is case sensitive */
6424 if (casesensitive && strncmp(text, item, string_length) == 0)
6425 {
6426 matches++;
6427 return pg_strdup(item);
6428 }
6429
6430 /* Second pass is case insensitive, don't bother counting matches */
6431 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
6432 {
6434 return pg_strdup(item);
6435 else
6436
6437 /*
6438 * If case insensitive matching was requested initially,
6439 * adjust the case according to setting.
6440 */
6441 return pg_strdup_keyword_case(item, text);
6442 }
6443 }
6444
6445 /*
6446 * No matches found. If we're not case insensitive already, lets switch to
6447 * being case insensitive and try again
6448 */
6449 if (casesensitive && matches == 0)
6450 {
6451 casesensitive = false;
6452 list_index = 0;
6453 state++;
6454 return complete_from_list(text, state);
6455 }
6456
6457 /* If no more matches, return null. */
6458 return NULL;
6459}
6460
6461
6462/*
6463 * This function returns one fixed string the first time even if it doesn't
6464 * match what's there, and nothing the second time. The string
6465 * to be used must be in completion_charp.
6466 *
6467 * If the given string is "", this has the effect of preventing readline
6468 * from doing any completion. (Without this, readline tries to do filename
6469 * completion which is seldom the right thing.)
6470 *
6471 * If the given string is not empty, readline will replace whatever the
6472 * user typed with that string. This behavior might be useful if it's
6473 * completely certain that we know what must appear at a certain spot,
6474 * so that it's okay to overwrite misspellings. In practice, given the
6475 * relatively lame parsing technology used in this file, the level of
6476 * certainty is seldom that high, so that you probably don't want to
6477 * use this. Use complete_from_list with a one-element list instead;
6478 * that won't try to auto-correct "misspellings".
6479 */
6480static char *
6481complete_from_const(const char *text, int state)
6482{
6484 if (state == 0)
6485 {
6488 else
6489
6490 /*
6491 * If case insensitive matching was requested initially, adjust
6492 * the case according to setting.
6493 */
6495 }
6496 else
6497 return NULL;
6498}
6499
6500
6501/*
6502 * This function appends the variable name with prefix and suffix to
6503 * the variable names array.
6504 */
6505static void
6506append_variable_names(char ***varnames, int *nvars,
6507 int *maxvars, const char *varname,
6508 const char *prefix, const char *suffix)
6509{
6510 if (*nvars >= *maxvars)
6511 {
6512 *maxvars *= 2;
6513 *varnames = pg_realloc_array(*varnames, char *, (*maxvars) + 1);
6514 }
6515
6516 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
6517}
6518
6519
6520/*
6521 * This function supports completion with the name of a psql variable.
6522 * The variable names can be prefixed and suffixed with additional text
6523 * to support quoting usages. If need_value is true, only variables
6524 * that are currently set are included; otherwise, special variables
6525 * (those that have hooks) are included even if currently unset.
6526 */
6527static char **
6528complete_from_variables(const char *text, const char *prefix, const char *suffix,
6529 bool need_value)
6530{
6531 char **matches;
6532 char **varnames;
6533 int nvars = 0;
6534 int maxvars = 100;
6535 int i;
6536 struct _variable *ptr;
6537
6538 varnames = pg_malloc_array(char *, maxvars + 1);
6539
6540 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
6541 {
6542 if (need_value && !(ptr->value))
6543 continue;
6544 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
6545 prefix, suffix);
6546 }
6547
6548 varnames[nvars] = NULL;
6549 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
6550
6551 for (i = 0; i < nvars; i++)
6552 free(varnames[i]);
6553 free(varnames);
6554
6555 return matches;
6556}
6557
6558
6559/*
6560 * This function returns in order one of a fixed, NULL pointer terminated list
6561 * of string that matches file names or optionally specified list of keywords.
6562 *
6563 * If completion_charpp is set to a null-terminated array of literal keywords,
6564 * those keywords are added to the completion results alongside filenames if
6565 * they case-insensitively match the current input.
6566 */
6567static char *
6568complete_from_files(const char *text, int state)
6569{
6570 static int list_index;
6571 static bool files_done;
6572 const char *item;
6573
6574 /* Initialization */
6575 if (state == 0)
6576 {
6577 list_index = 0;
6578 files_done = false;
6579 }
6580
6581 if (!files_done)
6582 {
6584
6585 /* Return a filename that matches */
6586 if (result)
6587 return result;
6588
6589 /* There are no more matching files */
6590 files_done = true;
6591 }
6592
6593 if (!completion_charpp)
6594 return NULL;
6595
6596 /*
6597 * Check for hard-wired keywords. These will only be returned if they
6598 * match the input-so-far, ignoring case.
6599 */
6600 while ((item = completion_charpp[list_index++]))
6601 {
6602 if (pg_strncasecmp(text, item, strlen(text)) == 0)
6603 {
6604 completion_force_quote = false;
6605 return pg_strdup_keyword_case(item, text);
6606 }
6607 }
6608
6609 return NULL;
6610}
6611
6612/*
6613 * This function wraps rl_filename_completion_function() to strip quotes from
6614 * the input before searching for matches and to quote any matches for which
6615 * the consuming command will require it.
6616 *
6617 * Caller must set completion_charp to a zero- or one-character string
6618 * containing the escape character. This is necessary since \copy has no
6619 * escape character, but every other backslash command recognizes "\" as an
6620 * escape character.
6621 *
6622 * Caller must also set completion_force_quote to indicate whether to force
6623 * quotes around the result. (The SQL COPY command requires that.)
6624 */
6625static char *
6626_complete_from_files(const char *text, int state)
6627{
6628#ifdef USE_FILENAME_QUOTING_FUNCTIONS
6629
6630 /*
6631 * If we're using a version of Readline that supports filename quoting
6632 * hooks, rely on those, and invoke rl_filename_completion_function()
6633 * without messing with its arguments. Readline does stuff internally
6634 * that does not work well at all if we try to handle dequoting here.
6635 * Instead, Readline will call quote_file_name() and dequote_file_name()
6636 * (see below) at appropriate times.
6637 *
6638 * ... or at least, mostly it will. There are some paths involving
6639 * unmatched file names in which Readline never calls quote_file_name(),
6640 * and if left to its own devices it will incorrectly append a quote
6641 * anyway. Set rl_completion_suppress_quote to prevent that. If we do
6642 * get to quote_file_name(), we'll clear this again. (Yes, this seems
6643 * like it's working around Readline bugs.)
6644 */
6645#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
6647#endif
6648
6649 /* If user typed a quote, force quoting (never remove user's quote) */
6650 if (*text == '\'')
6652
6654#else
6655
6656 /*
6657 * Otherwise, we have to do the best we can.
6658 */
6659 static const char *unquoted_text;
6660 char *unquoted_match;
6661 char *ret = NULL;
6662
6663 /* If user typed a quote, force quoting (never remove user's quote) */
6664 if (*text == '\'')
6666
6667 if (state == 0)
6668 {
6669 /* Initialization: stash the unquoted input. */
6671 false, true, pset.encoding);
6672 /* expect a NULL return for the empty string only */
6673 if (!unquoted_text)
6674 {
6675 Assert(*text == '\0');
6677 }
6678 }
6679
6681 if (unquoted_match)
6682 {
6683 struct stat statbuf;
6684 bool is_dir = (stat(unquoted_match, &statbuf) == 0 &&
6685 S_ISDIR(statbuf.st_mode) != 0);
6686
6687 /* Re-quote the result, if needed. */
6688 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
6689 '\'', *completion_charp,
6691 pset.encoding);
6692 if (ret)
6694 else
6695 ret = unquoted_match;
6696
6697 /*
6698 * If it's a directory, replace trailing quote with a slash; this is
6699 * usually more convenient. (If we didn't quote, leave this to
6700 * libedit.)
6701 */
6702 if (*ret == '\'' && is_dir)
6703 {
6704 char *retend = ret + strlen(ret) - 1;
6705
6706 Assert(*retend == '\'');
6707 *retend = '/';
6708 /* Prevent libedit from adding a space, too */
6710 }
6711 }
6712
6713 return ret;
6714#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
6715}
6716
6717
6718/* HELPER FUNCTIONS */
6719
6720
6721/*
6722 * Make a pg_strdup copy of s and convert the case according to
6723 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
6724 */
6725static char *
6726pg_strdup_keyword_case(const char *s, const char *ref)
6727{
6728 char *ret,
6729 *p;
6730 unsigned char first = ref[0];
6731
6732 ret = pg_strdup(s);
6733
6738 {
6739 for (p = ret; *p; p++)
6740 *p = pg_tolower((unsigned char) *p);
6741 }
6742 else
6743 {
6744 for (p = ret; *p; p++)
6745 *p = pg_toupper((unsigned char) *p);
6746 }
6747
6748 return ret;
6749}
6750
6751
6752/*
6753 * escape_string - Escape argument for use as string literal.
6754 *
6755 * The returned value has to be freed.
6756 */
6757static char *
6758escape_string(const char *text)
6759{
6760 size_t text_length;
6761 char *result;
6762
6764
6765 result = pg_malloc(text_length * 2 + 1);
6767
6768 return result;
6769}
6770
6771
6772/*
6773 * make_like_pattern - Convert argument to a LIKE prefix pattern.
6774 *
6775 * We escape _ and % in the given text by backslashing, append a % to
6776 * represent "any subsequent characters", and then pass the string through
6777 * escape_string() so it's ready to insert in a query. The result needs
6778 * to be freed.
6779 */
6780static char *
6781make_like_pattern(const char *word)
6782{
6783 char *result;
6784 char *buffer = pg_malloc(strlen(word) * 2 + 2);
6785 char *bptr = buffer;
6786
6787 while (*word)
6788 {
6789 if (*word == '_' || *word == '%')
6790 *bptr++ = '\\';
6791 if (IS_HIGHBIT_SET(*word))
6792 {
6793 /*
6794 * Transfer multibyte characters without further processing, to
6795 * avoid getting confused in unsafe client encodings.
6796 */
6798
6799 while (chlen-- > 0)
6800 *bptr++ = *word++;
6801 }
6802 else
6803 *bptr++ = *word++;
6804 }
6805 *bptr++ = '%';
6806 *bptr = '\0';
6807
6808 result = escape_string(buffer);
6809 free(buffer);
6810 return result;
6811}
6812
6813
6814/*
6815 * parse_identifier - Parse a possibly-schema-qualified SQL identifier.
6816 *
6817 * This involves splitting off the schema name if present, de-quoting,
6818 * and downcasing any unquoted text. We are a bit laxer than the backend
6819 * in that we allow just portions of a name to be quoted --- that's because
6820 * psql metacommands have traditionally behaved that way.
6821 *
6822 * Outputs are a malloc'd schema name (NULL if none), malloc'd object name,
6823 * and booleans telling whether any part of the schema and object name was
6824 * double-quoted.
6825 */
6826static void
6827parse_identifier(const char *ident,
6828 char **schemaname, char **objectname,
6829 bool *schemaquoted, bool *objectquoted)
6830{
6831 size_t buflen = strlen(ident) + 1;
6833 char *sname;
6834 char *oname;
6835 char *optr;
6836 bool inquotes;
6837
6838 /* Initialize, making a certainly-large-enough output buffer */
6839 sname = NULL;
6840 oname = pg_malloc(buflen);
6841 *schemaquoted = *objectquoted = false;
6842 /* Scan */
6843 optr = oname;
6844 inquotes = false;
6845 while (*ident)
6846 {
6847 unsigned char ch = (unsigned char) *ident++;
6848
6849 if (ch == '"')
6850 {
6851 if (inquotes && *ident == '"')
6852 {
6853 /* two quote marks within a quoted identifier = emit quote */
6854 *optr++ = '"';
6855 ident++;
6856 }
6857 else
6858 {
6859 inquotes = !inquotes;
6860 *objectquoted = true;
6861 }
6862 }
6863 else if (ch == '.' && !inquotes)
6864 {
6865 /* Found a schema name, transfer it to sname / *schemaquoted */
6866 *optr = '\0';
6867 free(sname); /* drop any catalog name */
6868 sname = oname;
6869 oname = pg_malloc(buflen);
6870 optr = oname;
6872 *objectquoted = false;
6873 }
6874 else if (!enc_is_single_byte && IS_HIGHBIT_SET(ch))
6875 {
6876 /*
6877 * Transfer multibyte characters without further processing. They
6878 * wouldn't be affected by our downcasing rule anyway, and this
6879 * avoids possibly doing the wrong thing in unsafe client
6880 * encodings.
6881 */
6883
6884 *optr++ = (char) ch;
6885 while (--chlen > 0)
6886 *optr++ = *ident++;
6887 }
6888 else
6889 {
6890 if (!inquotes)
6891 {
6892 /*
6893 * This downcasing transformation should match the backend's
6894 * downcase_identifier() as best we can. We do not know the
6895 * backend's locale, though, so it's necessarily approximate.
6896 * We assume that psql is operating in the same locale and
6897 * encoding as the backend.
6898 */
6899 if (ch >= 'A' && ch <= 'Z')
6900 ch += 'a' - 'A';
6902 ch = tolower(ch);
6903 }
6904 *optr++ = (char) ch;
6905 }
6906 }
6907
6908 *optr = '\0';
6909 *schemaname = sname;
6910 *objectname = oname;
6911}
6912
6913
6914/*
6915 * requote_identifier - Reconstruct a possibly-schema-qualified SQL identifier.
6916 *
6917 * Build a malloc'd string containing the identifier, with quoting applied
6918 * as necessary. This is more or less the inverse of parse_identifier;
6919 * in particular, if an input component was quoted, we'll quote the output
6920 * even when that isn't strictly required.
6921 *
6922 * Unlike parse_identifier, we handle the case where a schema and no
6923 * object name is provided, producing just "schema.".
6924 */
6925static char *
6926requote_identifier(const char *schemaname, const char *objectname,
6927 bool quote_schema, bool quote_object)
6928{
6929 char *result;
6930 size_t buflen = 1; /* count the trailing \0 */
6931 char *ptr;
6932
6933 /*
6934 * We could use PQescapeIdentifier for some of this, but not all, and it
6935 * adds more notational cruft than it seems worth.
6936 */
6937 if (schemaname)
6938 {
6939 buflen += strlen(schemaname) + 1; /* +1 for the dot */
6940 if (!quote_schema)
6942 if (quote_schema)
6943 {
6944 buflen += 2; /* account for quote marks */
6945 for (const char *p = schemaname; *p; p++)
6946 {
6947 if (*p == '"')
6948 buflen++;
6949 }
6950 }
6951 }
6952 if (objectname)
6953 {
6954 buflen += strlen(objectname);
6955 if (!quote_object)
6957 if (quote_object)
6958 {
6959 buflen += 2; /* account for quote marks */
6960 for (const char *p = objectname; *p; p++)
6961 {
6962 if (*p == '"')
6963 buflen++;
6964 }
6965 }
6966 }
6967 result = pg_malloc(buflen);
6968 ptr = result;
6969 if (schemaname)
6970 {
6971 if (quote_schema)
6972 *ptr++ = '"';
6973 for (const char *p = schemaname; *p; p++)
6974 {
6975 *ptr++ = *p;
6976 if (*p == '"')
6977 *ptr++ = '"';
6978 }
6979 if (quote_schema)
6980 *ptr++ = '"';
6981 *ptr++ = '.';
6982 }
6983 if (objectname)
6984 {
6985 if (quote_object)
6986 *ptr++ = '"';
6987 for (const char *p = objectname; *p; p++)
6988 {
6989 *ptr++ = *p;
6990 if (*p == '"')
6991 *ptr++ = '"';
6992 }
6993 if (quote_object)
6994 *ptr++ = '"';
6995 }
6996 *ptr = '\0';
6997 return result;
6998}
6999
7000
7001/*
7002 * Detect whether an identifier must be double-quoted.
7003 *
7004 * Note we'll quote anything that's not ASCII; the backend's quote_ident()
7005 * does the same. Perhaps this could be relaxed in future.
7006 */
7007static bool
7008identifier_needs_quotes(const char *ident)
7009{
7010 int kwnum;
7011
7012 /* Check syntax. */
7013 if (!((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_'))
7014 return true;
7015 if (strspn(ident, "abcdefghijklmnopqrstuvwxyz0123456789_$") != strlen(ident))
7016 return true;
7017
7018 /*
7019 * Check for keyword. We quote keywords except for unreserved ones.
7020 *
7021 * It is possible that our keyword list doesn't quite agree with the
7022 * server's, but this should be close enough for tab-completion purposes.
7023 *
7024 * Note: ScanKeywordLookup() does case-insensitive comparison, but that's
7025 * fine, since we already know we have all-lower-case.
7026 */
7028
7030 return true;
7031
7032 return false;
7033}
7034
7035
7036/*
7037 * Execute a query, returning NULL if there was any error.
7038 * This should be the preferred way of talking to the database in this file.
7039 */
7040static PGresult *
7041exec_query(const char *query)
7042{
7044
7045 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
7046 return NULL;
7047
7048 result = PQexec(pset.db, query);
7049
7051 {
7052 /*
7053 * Printing an error while the user is typing would be quite annoying,
7054 * so we don't. This does complicate debugging of this code; but you
7055 * can look in the server log instead.
7056 */
7057#ifdef NOT_USED
7058 pg_log_error("tab completion query failed: %s\nQuery was:\n%s",
7059 PQerrorMessage(pset.db), query);
7060#endif
7061 PQclear(result);
7062 result = NULL;
7063 }
7064
7065 return result;
7066}
7067
7068
7069/*
7070 * Parse all the word(s) before point.
7071 *
7072 * Returns a malloc'd array of character pointers that point into the malloc'd
7073 * data array returned to *buffer; caller must free() both of these when done.
7074 * *nwords receives the number of words found, ie, the valid length of the
7075 * return array.
7076 *
7077 * Words are returned right to left, that is, previous_words[0] gets the last
7078 * word before point, previous_words[1] the next-to-last, etc.
7079 */
7080static char **
7081get_previous_words(int point, char **buffer, int *nwords)
7082{
7083 char **previous_words;
7084 char *buf;
7085 char *outptr;
7086 int words_found = 0;
7087 int i;
7088
7089 /*
7090 * If we have anything in tab_completion_query_buf, paste it together with
7091 * rl_line_buffer to construct the full query. Otherwise we can just use
7092 * rl_line_buffer as the input string.
7093 */
7095 {
7097 buf = pg_malloc(point + i + 2);
7099 buf[i++] = '\n';
7101 i += point;
7102 buf[i] = '\0';
7103 /* Readjust point to reference appropriate offset in buf */
7104 point = i;
7105 }
7106 else
7108
7109 /*
7110 * Allocate an array of string pointers and a buffer to hold the strings
7111 * themselves. The worst case is that the line contains only
7112 * non-whitespace WORD_BREAKS characters, making each one a separate word.
7113 * This is usually much more space than we need, but it's cheaper than
7114 * doing a separate malloc() for each word.
7115 */
7117 *buffer = outptr = (char *) pg_malloc(point * 2);
7118
7119 /*
7120 * First we look for a non-word char before the current point. (This is
7121 * probably useless, if readline is on the same page as we are about what
7122 * is a word, but if so it's cheap.)
7123 */
7124 for (i = point - 1; i >= 0; i--)
7125 {
7126 if (strchr(WORD_BREAKS, buf[i]))
7127 break;
7128 }
7129 point = i;
7130
7131 /*
7132 * Now parse words, working backwards, until we hit start of line. The
7133 * backwards scan has some interesting but intentional properties
7134 * concerning parenthesis handling.
7135 */
7136 while (point >= 0)
7137 {
7138 int start,
7139 end;
7140 bool inquotes = false;
7141 int parentheses = 0;
7142
7143 /* now find the first non-space which then constitutes the end */
7144 end = -1;
7145 for (i = point; i >= 0; i--)
7146 {
7147 if (!isspace((unsigned char) buf[i]))
7148 {
7149 end = i;
7150 break;
7151 }
7152 }
7153 /* if no end found, we're done */
7154 if (end < 0)
7155 break;
7156
7157 /*
7158 * Otherwise we now look for the start. The start is either the last
7159 * character before any word-break character going backwards from the
7160 * end, or it's simply character 0. We also handle open quotes and
7161 * parentheses.
7162 */
7163 for (start = end; start > 0; start--)
7164 {
7165 if (buf[start] == '"')
7166 inquotes = !inquotes;
7167 if (!inquotes)
7168 {
7169 if (buf[start] == ')')
7170 parentheses++;
7171 else if (buf[start] == '(')
7172 {
7173 if (--parentheses <= 0)
7174 break;
7175 }
7176 else if (parentheses == 0 &&
7177 strchr(WORD_BREAKS, buf[start - 1]))
7178 break;
7179 }
7180 }
7181
7182 /* Return the word located at start to end inclusive */
7184 i = end - start + 1;
7185 memcpy(outptr, &buf[start], i);
7186 outptr += i;
7187 *outptr++ = '\0';
7188
7189 /* Continue searching */
7190 point = start - 1;
7191 }
7192
7193 /* Release parsing input workspace, if we made one above */
7194 if (buf != rl_line_buffer)
7195 free(buf);
7196
7197 *nwords = words_found;
7198 return previous_words;
7199}
7200
7201/*
7202 * Look up the type for the GUC variable with the passed name.
7203 *
7204 * Returns NULL if the variable is unknown. Otherwise the returned string,
7205 * containing the type, has to be freed.
7206 */
7207static char *
7208get_guctype(const char *varname)
7209{
7211 char *e_varname;
7213 char *guctype = NULL;
7214
7215 e_varname = escape_string(varname);
7216
7219 "SELECT vartype FROM pg_catalog.pg_settings "
7220 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
7221 e_varname);
7222
7225 free(e_varname);
7226
7229
7230 PQclear(result);
7231
7232 return guctype;
7233}
7234
7235#ifdef USE_FILENAME_QUOTING_FUNCTIONS
7236
7237/*
7238 * Quote a filename according to SQL rules, returning a malloc'd string.
7239 * completion_charp must point to escape character or '\0', and
7240 * completion_force_quote must be set correctly, as per comments for
7241 * complete_from_files().
7242 */
7243static char *
7244quote_file_name(char *fname, int match_type, char *quote_pointer)
7245{
7246 char *s;
7247 struct stat statbuf;
7248
7249 /* Quote if needed. */
7250 s = quote_if_needed(fname, " \t\r\n\"`",
7251 '\'', *completion_charp,
7253 pset.encoding);
7254 if (!s)
7255 s = pg_strdup(fname);
7256
7257 /*
7258 * However, some of the time we have to strip the trailing quote from what
7259 * we send back. Never strip the trailing quote if the user already typed
7260 * one; otherwise, suppress the trailing quote if we have multiple/no
7261 * matches (because we don't want to add a quote if the input is seemingly
7262 * unfinished), or if the input was already quoted (because Readline will
7263 * do arguably-buggy things otherwise), or if the file does not exist, or
7264 * if it's a directory.
7265 */
7266 if (*s == '\'' &&
7267 completion_last_char != '\'' &&
7269 (quote_pointer && *quote_pointer == '\'') ||
7270 stat(fname, &statbuf) != 0 ||
7271 S_ISDIR(statbuf.st_mode)))
7272 {
7273 char *send = s + strlen(s) - 1;
7274
7275 Assert(*send == '\'');
7276 *send = '\0';
7277 }
7278
7279 /*
7280 * And now we can let Readline do its thing with possibly adding a quote
7281 * on its own accord. (This covers some additional cases beyond those
7282 * dealt with above.)
7283 */
7284#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
7286#endif
7287
7288 /*
7289 * If user typed a leading quote character other than single quote (i.e.,
7290 * double quote), zap it, so that we replace it with the correct single
7291 * quote.
7292 */
7293 if (quote_pointer && *quote_pointer != '\'')
7294 *quote_pointer = '\0';
7295
7296 return s;
7297}
7298
7299/*
7300 * Dequote a filename, if it's quoted.
7301 * completion_charp must point to escape character or '\0', as per
7302 * comments for complete_from_files().
7303 */
7304static char *
7305dequote_file_name(char *fname, int quote_char)
7306{
7307 char *unquoted_fname;
7308
7309 /*
7310 * If quote_char is set, it's not included in "fname". We have to add it
7311 * or strtokx will not interpret the string correctly (notably, it won't
7312 * recognize escapes).
7313 */
7314 if (quote_char == '\'')
7315 {
7316 char *workspace = (char *) pg_malloc(strlen(fname) + 2);
7317
7318 workspace[0] = quote_char;
7319 strcpy(workspace + 1, fname);
7320 unquoted_fname = strtokx(workspace, "", NULL, "'", *completion_charp,
7321 false, true, pset.encoding);
7322 free(workspace);
7323 }
7324 else
7325 unquoted_fname = strtokx(fname, "", NULL, "'", *completion_charp,
7326 false, true, pset.encoding);
7327
7328 /* expect a NULL return for the empty string only */
7329 if (!unquoted_fname)
7330 {
7331 Assert(*fname == '\0');
7332 unquoted_fname = fname;
7333 }
7334
7335 /* readline expects a malloc'd result that it is to free */
7336 return pg_strdup(unquoted_fname);
7337}
7338
7339#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
7340
7341#endif /* USE_READLINE */
bool recognized_connection_string(const char *connstr)
Definition common.c:2747
#define IS_HIGHBIT_SET(ch)
Definition c.h:1244
#define Assert(condition)
Definition c.h:943
#define CppAsString2(x)
Definition c.h:506
uint32_t uint32
Definition c.h:624
#define lengthof(array)
Definition c.h:873
varlena text
Definition c.h:789
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition keywords.c:29
Datum arg
Definition elog.c:1323
ConnStatusType PQstatus(const PGconn *conn)
char * PQerrorMessage(const PGconn *conn)
size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)
Definition fe-exec.c:4213
PGresult * PQexec(PGconn *conn, const char *query)
Definition fe-exec.c:2279
int PQmblenBounded(const char *s, int encoding)
Definition fe-misc.c:1266
void * pg_malloc(size_t size)
Definition fe_memutils.c:53
char * pg_strdup(const char *in)
Definition fe_memutils.c:91
#define pg_realloc_array(pointer, type, count)
Definition fe_memutils.h:74
#define pg_malloc_array(type, count)
Definition fe_memutils.h:66
return str start
#define ident
int i
Definition isn.c:77
static const JsonPathKeyword keywords[]
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define UNRESERVED_KEYWORD
Definition keywords.h:20
int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)
Definition kwlookup.c:38
#define PQgetvalue
#define PQclear
#define PQnfields
#define PQresultStatus
#define PQgetisnull
#define PQntuples
@ CONNECTION_OK
Definition libpq-fe.h:90
@ PGRES_TUPLES_OK
Definition libpq-fe.h:134
#define pg_log_error(...)
Definition logging.h:108
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1921
static char buf[DEFAULT_XLOG_SEG_SIZE]
int pg_strcasecmp(const char *s1, const char *s2)
unsigned char pg_toupper(unsigned char ch)
unsigned char pg_tolower(unsigned char ch)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
void initPQExpBuffer(PQExpBuffer str)
Definition pqexpbuffer.c:90
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
char * c
static int fb(int x)
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition regcomp.c:1477
PsqlSettings pset
Definition startup.c:33
@ PSQL_COMP_CASE_PRESERVE_LOWER
Definition settings.h:66
@ PSQL_COMP_CASE_LOWER
Definition settings.h:68
@ PSQL_COMP_CASE_PRESERVE_UPPER
Definition settings.h:65
#define free(a)
char * strtokx(const char *s, const char *whitespace, const char *delim, const char *quote, char escape, bool e_strings, bool del_quotes, int encoding)
Definition stringutils.c:52
char * quote_if_needed(const char *source, const char *entails_quote, char quote, char escape, bool force_quote, int encoding)
VariableSpace vars
Definition settings.h:151
PSQL_COMP_CASE comp_case
Definition settings.h:179
PGconn * db
Definition settings.h:103
const char * progname
Definition settings.h:142
struct _variable * next
Definition variables.h:68
char * name
Definition variables.h:64
char * value
Definition variables.h:65
Definition c.h:776
void initialize_readline(void)
PQExpBuffer tab_completion_query_buf
static bool escape_string(PGconn *conn, PQExpBuffer target, const char *unescaped, size_t unescaped_len, PQExpBuffer escape_err)
static int32 text_length(Datum str)
Definition varlena.c:410
const char * name
int pg_encoding_max_length(int encoding)
Definition wchar.c:2013
#define stat
Definition win32_port.h:74
#define S_ISDIR(m)
Definition win32_port.h:315
#define send(s, buf, len, flags)
Definition win32_port.h:502