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