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