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