PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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", "\\endpipeline", "\\errverbose", "\\ev",
1889 "\\f", "\\flush", "\\flushrequest",
1890 "\\g", "\\gdesc", "\\getenv", "\\getresults", "\\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", "\\sendpipeline", "\\set", "\\setenv", "\\sf",
1899 "\\startpipeline", "\\sv", "\\syncpipeline",
1900 "\\t", "\\T", "\\timing",
1901 "\\unset",
1902 "\\x",
1903 "\\warn", "\\watch", "\\write",
1904 "\\z",
1905 "\\!", "\\?",
1906 NULL
1907 };
1908
1909 /*
1910 * Temporary workaround for a bug in recent (2019) libedit: it incorrectly
1911 * de-escapes the input "text", causing us to fail to recognize backslash
1912 * commands. So get the string to look at from rl_line_buffer instead.
1913 */
1914 char *text_copy = pnstrdup(rl_line_buffer + start, end - start);
1915 text = text_copy;
1916
1917 /* Remember last char of the given input word. */
1918 completion_last_char = (end > start) ? text[end - start - 1] : '\0';
1919
1920 /* We usually want the append character to be a space. */
1921 rl_completion_append_character = ' ';
1922
1923 /* Clear a few things. */
1924 completion_charp = NULL;
1925 completion_charpp = NULL;
1926 completion_vquery = NULL;
1927 completion_squery = NULL;
1928 completion_ref_object = NULL;
1929 completion_ref_schema = NULL;
1930
1931 /*
1932 * Scan the input line to extract the words before our current position.
1933 * According to those we'll make some smart decisions on what the user is
1934 * probably intending to type.
1935 */
1936 previous_words = get_previous_words(start,
1937 &words_buffer,
1938 &previous_words_count);
1939
1940 /* If current word is a backslash command, offer completions for that */
1941 if (text[0] == '\\')
1942 COMPLETE_WITH_LIST_CS(backslash_commands);
1943
1944 /* If current word is a variable interpolation, handle that case */
1945 else if (text[0] == ':' && text[1] != ':')
1946 {
1947 if (text[1] == '\'')
1948 matches = complete_from_variables(text, ":'", "'", true);
1949 else if (text[1] == '"')
1950 matches = complete_from_variables(text, ":\"", "\"", true);
1951 else if (text[1] == '{' && text[2] == '?')
1952 matches = complete_from_variables(text, ":{?", "}", true);
1953 else
1954 matches = complete_from_variables(text, ":", "", true);
1955 }
1956
1957 /* If no previous word, suggest one of the basic sql commands */
1958 else if (previous_words_count == 0)
1959 COMPLETE_WITH_LIST(sql_commands);
1960
1961 /* Else try completions based on matching patterns of previous words */
1962 else
1963 {
1964#ifdef SWITCH_CONVERSION_APPLIED
1965 /*
1966 * If we have transformed match_previous_words into a switch, iterate
1967 * through tcpatterns[] to see which pattern ids match.
1968 *
1969 * For now, we have to try the patterns in the order they are stored
1970 * (matching the order of switch cases in match_previous_words),
1971 * because some of the logic in match_previous_words assumes that
1972 * previous matches have been eliminated. This is fairly
1973 * unprincipled, and it is likely that there are undesirable as well
1974 * as desirable interactions hidden in the order of the pattern
1975 * checks. TODO: think about a better way to manage that.
1976 */
1977 for (int tindx = 0; tindx < lengthof(tcpatterns); tindx++)
1978 {
1979 const TCPattern *tcpat = tcpatterns + tindx;
1980 bool match = false;
1981
1982 switch (tcpat->kind)
1983 {
1984 case Match:
1985 match = MatchesArray(false,
1986 previous_words_count,
1987 previous_words,
1988 tcpat->nwords, tcpat->words);
1989 break;
1990 case MatchCS:
1991 match = MatchesArray(true,
1992 previous_words_count,
1993 previous_words,
1994 tcpat->nwords, tcpat->words);
1995 break;
1996 case HeadMatch:
1997 match = HeadMatchesArray(false,
1998 previous_words_count,
1999 previous_words,
2000 tcpat->nwords, tcpat->words);
2001 break;
2002 case HeadMatchCS:
2003 match = HeadMatchesArray(true,
2004 previous_words_count,
2005 previous_words,
2006 tcpat->nwords, tcpat->words);
2007 break;
2008 case TailMatch:
2009 match = TailMatchesArray(false,
2010 previous_words_count,
2011 previous_words,
2012 tcpat->nwords, tcpat->words);
2013 break;
2014 case TailMatchCS:
2015 match = TailMatchesArray(true,
2016 previous_words_count,
2017 previous_words,
2018 tcpat->nwords, tcpat->words);
2019 break;
2020 }
2021 if (match)
2022 {
2023 matches = match_previous_words(tcpat->id, text, start, end,
2024 previous_words,
2025 previous_words_count);
2026 if (matches != NULL)
2027 break;
2028 }
2029 }
2030#else /* !SWITCH_CONVERSION_APPLIED */
2031 /*
2032 * If gen_tabcomplete.pl hasn't been applied to this code, just let
2033 * match_previous_words scan through all its patterns.
2034 */
2035 matches = match_previous_words(0, text, start, end,
2036 previous_words,
2037 previous_words_count);
2038#endif /* SWITCH_CONVERSION_APPLIED */
2039 }
2040
2041 /*
2042 * Finally, we look through the list of "things", such as TABLE, INDEX and
2043 * check if that was the previous word. If so, execute the query to get a
2044 * list of them.
2045 */
2046 if (matches == NULL && previous_words_count > 0)
2047 {
2048 const pgsql_thing_t *wac;
2049
2050 for (wac = words_after_create; wac->name != NULL; wac++)
2051 {
2052 if (pg_strcasecmp(prev_wd, wac->name) == 0)
2053 {
2054 if (wac->query)
2055 COMPLETE_WITH_QUERY_LIST(wac->query,
2056 wac->keywords);
2057 else if (wac->vquery)
2058 COMPLETE_WITH_VERSIONED_QUERY_LIST(wac->vquery,
2059 wac->keywords);
2060 else if (wac->squery)
2061 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY_LIST(wac->squery,
2062 wac->keywords);
2063 break;
2064 }
2065 }
2066 }
2067
2068 /*
2069 * If we still don't have anything to match we have to fabricate some sort
2070 * of default list. If we were to just return NULL, readline automatically
2071 * attempts filename completion, and that's usually no good.
2072 */
2073 if (matches == NULL)
2074 {
2075 COMPLETE_WITH_CONST(true, "");
2076 /* Also, prevent Readline from appending stuff to the non-match */
2077 rl_completion_append_character = '\0';
2078#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
2079 rl_completion_suppress_quote = 1;
2080#endif
2081 }
2082
2083 /* free storage */
2084 free(previous_words);
2085 free(words_buffer);
2086 free(text_copy);
2087 free(completion_ref_object);
2088 completion_ref_object = NULL;
2089 free(completion_ref_schema);
2090 completion_ref_schema = NULL;
2091
2092 /* Return our Grand List O' Matches */
2093 return matches;
2094}
2095
2096/*
2097 * Subroutine to try matches based on previous_words.
2098 *
2099 * This can operate in one of two modes. As presented, the body of the
2100 * function is a long if-else-if chain that sequentially tries each known
2101 * match rule. That works, but some C compilers have trouble with such a long
2102 * else-if chain, either taking extra time to compile or failing altogether.
2103 * Therefore, we prefer to transform the else-if chain into a switch, and then
2104 * each call of this function considers just one match rule (under control of
2105 * a loop in psql_completion()). Compilers tend to be more ready to deal
2106 * with many-arm switches than many-arm else-if chains.
2107 *
2108 * Each if-condition in this function must begin with a call of one of the
2109 * functions Matches, HeadMatches, TailMatches, MatchesCS, HeadMatchesCS, or
2110 * TailMatchesCS. The preprocessor gen_tabcomplete.pl strips out those
2111 * calls and converts them into entries in tcpatterns[], which are evaluated
2112 * by the calling loop in psql_completion(). Successful matches result in
2113 * calls to this function with the appropriate pattern_id, causing just the
2114 * corresponding switch case to be executed.
2115 *
2116 * If-conditions in this function can be more complex than a single *Matches
2117 * function call in one of two ways (but not both!). They can be OR's
2118 * of *Matches calls, such as
2119 * else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
2120 * Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
2121 * or they can be a *Matches call AND'ed with some other condition, e.g.
2122 * else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) &&
2123 * !ends_with(prev_wd, ','))
2124 * The former case is transformed into multiple tcpatterns[] entries and
2125 * multiple case labels for the same bit of code. The latter case is
2126 * transformed into a case label and a contained if-statement.
2127 *
2128 * This is split out of psql_completion() primarily to separate code that
2129 * gen_tabcomplete.pl should process from code that it should not, although
2130 * doing so also helps to avoid extra indentation of this code.
2131 *
2132 * Returns a matches list, or NULL if no match.
2133 */
2134static char **
2135match_previous_words(int pattern_id,
2136 const char *text, int start, int end,
2137 char **previous_words, int previous_words_count)
2138{
2139 /* This is the variable we'll return. */
2140 char **matches = NULL;
2141
2142 /* Dummy statement, allowing all the match rules to look like "else if" */
2143 if (0)
2144 {
2145 /* skip */
2146 }
2147
2148 /* gen_tabcomplete.pl begins special processing here */
2149 /* BEGIN GEN_TABCOMPLETE */
2150
2151/* CREATE */
2152 /* complete with something you can create */
2153 else if (TailMatches("CREATE"))
2154 {
2155 /* only some object types can be created as part of CREATE SCHEMA */
2156 if (HeadMatches("CREATE", "SCHEMA"))
2157 COMPLETE_WITH("TABLE", "VIEW", "INDEX", "SEQUENCE", "TRIGGER",
2158 /* for INDEX and TABLE/SEQUENCE, respectively */
2159 "UNIQUE", "UNLOGGED");
2160 else
2161 matches = rl_completion_matches(text, create_command_generator);
2162 }
2163 /* complete with something you can create or replace */
2164 else if (TailMatches("CREATE", "OR", "REPLACE"))
2165 COMPLETE_WITH("FUNCTION", "PROCEDURE", "LANGUAGE", "RULE", "VIEW",
2166 "AGGREGATE", "TRANSFORM", "TRIGGER");
2167
2168/* DROP, but not DROP embedded in other commands */
2169 /* complete with something you can drop */
2170 else if (Matches("DROP"))
2171 matches = rl_completion_matches(text, drop_command_generator);
2172
2173/* ALTER */
2174
2175 /* ALTER TABLE */
2176 else if (Matches("ALTER", "TABLE"))
2177 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
2178 "ALL IN TABLESPACE");
2179
2180 /* ALTER something */
2181 else if (Matches("ALTER"))
2182 matches = rl_completion_matches(text, alter_command_generator);
2183 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
2184 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny))
2185 COMPLETE_WITH("SET TABLESPACE", "OWNED BY");
2186 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
2187 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
2188 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2189 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
2190 else if (TailMatches("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
2191 COMPLETE_WITH("SET TABLESPACE");
2192 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
2193 else if (Matches("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
2194 COMPLETE_WITH("(");
2195 /* ALTER AGGREGATE <name> (...) */
2196 else if (Matches("ALTER", "AGGREGATE", MatchAny, MatchAny))
2197 {
2198 if (ends_with(prev_wd, ')'))
2199 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
2200 else
2201 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2202 }
2203 /* ALTER FUNCTION <name> (...) */
2204 else if (Matches("ALTER", "FUNCTION", MatchAny, MatchAny))
2205 {
2206 if (ends_with(prev_wd, ')'))
2207 COMPLETE_WITH(Alter_function_options);
2208 else
2209 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2210 }
2211 /* ALTER PROCEDURE <name> (...) */
2212 else if (Matches("ALTER", "PROCEDURE", MatchAny, MatchAny))
2213 {
2214 if (ends_with(prev_wd, ')'))
2215 COMPLETE_WITH(Alter_procedure_options);
2216 else
2217 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2218 }
2219 /* ALTER ROUTINE <name> (...) */
2220 else if (Matches("ALTER", "ROUTINE", MatchAny, MatchAny))
2221 {
2222 if (ends_with(prev_wd, ')'))
2223 COMPLETE_WITH(Alter_routine_options);
2224 else
2225 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2226 }
2227 /* ALTER FUNCTION|ROUTINE <name> (...) PARALLEL */
2228 else if (Matches("ALTER", "FUNCTION|ROUTINE", MatchAny, MatchAny, "PARALLEL"))
2229 COMPLETE_WITH("RESTRICTED", "SAFE", "UNSAFE");
2230 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) [EXTERNAL] SECURITY */
2231 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SECURITY") ||
2232 Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "EXTERNAL", "SECURITY"))
2233 COMPLETE_WITH("DEFINER", "INVOKER");
2234 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) RESET */
2235 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "RESET"))
2236 COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
2237 "ALL");
2238 /* ALTER FUNCTION|PROCEDURE|ROUTINE <name> (...) SET */
2239 else if (Matches("ALTER", "FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny, "SET"))
2240 COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
2241 "SCHEMA");
2242
2243 /* ALTER PUBLICATION <name> */
2244 else if (Matches("ALTER", "PUBLICATION", MatchAny))
2245 COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME TO", "SET");
2246 /* ALTER PUBLICATION <name> ADD */
2247 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD"))
2248 COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
2249 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
2250 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2251 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
2252 ends_with(prev_wd, ','))
2253 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2254
2255 /*
2256 * "ALTER PUBLICATION <name> SET TABLE <name> WHERE (" - complete with
2257 * table attributes
2258 *
2259 * "ALTER PUBLICATION <name> ADD TABLE <name> WHERE (" - complete with
2260 * table attributes
2261 */
2262 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "WHERE"))
2263 COMPLETE_WITH("(");
2264 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "("))
2265 COMPLETE_WITH_ATTR(prev3_wd);
2266 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE") &&
2267 !TailMatches("WHERE", "(*)"))
2268 COMPLETE_WITH(",", "WHERE (");
2269 else if (HeadMatches("ALTER", "PUBLICATION", MatchAny, "ADD|SET", "TABLE"))
2270 COMPLETE_WITH(",");
2271 /* ALTER PUBLICATION <name> DROP */
2272 else if (Matches("ALTER", "PUBLICATION", MatchAny, "DROP"))
2273 COMPLETE_WITH("TABLES IN SCHEMA", "TABLE");
2274 /* ALTER PUBLICATION <name> SET */
2275 else if (Matches("ALTER", "PUBLICATION", MatchAny, "SET"))
2276 COMPLETE_WITH("(", "TABLES IN SCHEMA", "TABLE");
2277 else if (Matches("ALTER", "PUBLICATION", MatchAny, "ADD|DROP|SET", "TABLES", "IN", "SCHEMA"))
2278 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
2279 " AND nspname NOT LIKE E'pg\\\\_%%'",
2280 "CURRENT_SCHEMA");
2281 /* ALTER PUBLICATION <name> SET ( */
2282 else if (Matches("ALTER", "PUBLICATION", MatchAny, MatchAnyN, "SET", "("))
2283 COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root");
2284 /* ALTER SUBSCRIPTION <name> */
2285 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny))
2286 COMPLETE_WITH("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
2287 "RENAME TO", "REFRESH PUBLICATION", "SET", "SKIP (",
2288 "ADD PUBLICATION", "DROP PUBLICATION");
2289 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION */
2290 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH", "PUBLICATION"))
2291 COMPLETE_WITH("WITH (");
2292 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
2293 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "REFRESH", "PUBLICATION", "WITH", "("))
2294 COMPLETE_WITH("copy_data");
2295 /* ALTER SUBSCRIPTION <name> SET */
2296 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
2297 COMPLETE_WITH("(", "PUBLICATION");
2298 /* ALTER SUBSCRIPTION <name> SET ( */
2299 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "("))
2300 COMPLETE_WITH("binary", "disable_on_error", "failover", "origin",
2301 "password_required", "run_as_owner", "slot_name",
2302 "streaming", "synchronous_commit", "two_phase");
2303 /* ALTER SUBSCRIPTION <name> SKIP ( */
2304 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SKIP", "("))
2305 COMPLETE_WITH("lsn");
2306 /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
2307 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN, "SET", "PUBLICATION"))
2308 {
2309 /* complete with nothing here as this refers to remote publications */
2310 }
2311 /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> */
2312 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN,
2313 "ADD|DROP|SET", "PUBLICATION", MatchAny))
2314 COMPLETE_WITH("WITH (");
2315 /* ALTER SUBSCRIPTION <name> ADD|DROP|SET PUBLICATION <name> WITH ( */
2316 else if (Matches("ALTER", "SUBSCRIPTION", MatchAny, MatchAnyN,
2317 "ADD|DROP|SET", "PUBLICATION", MatchAny, "WITH", "("))
2318 COMPLETE_WITH("copy_data", "refresh");
2319
2320 /* ALTER SCHEMA <name> */
2321 else if (Matches("ALTER", "SCHEMA", MatchAny))
2322 COMPLETE_WITH("OWNER TO", "RENAME TO");
2323
2324 /* ALTER COLLATION <name> */
2325 else if (Matches("ALTER", "COLLATION", MatchAny))
2326 COMPLETE_WITH("OWNER TO", "REFRESH VERSION", "RENAME TO", "SET SCHEMA");
2327
2328 /* ALTER CONVERSION <name> */
2329 else if (Matches("ALTER", "CONVERSION", MatchAny))
2330 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA");
2331
2332 /* ALTER DATABASE <name> */
2333 else if (Matches("ALTER", "DATABASE", MatchAny))
2334 COMPLETE_WITH("RESET", "SET", "OWNER TO", "REFRESH COLLATION VERSION", "RENAME TO",
2335 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
2336 "CONNECTION LIMIT");
2337
2338 /* ALTER DATABASE <name> RESET */
2339 else if (Matches("ALTER", "DATABASE", MatchAny, "RESET"))
2340 {
2341 set_completion_reference(prev2_wd);
2342 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_database_vars, "ALL");
2343 }
2344
2345 /* ALTER DATABASE <name> SET TABLESPACE */
2346 else if (Matches("ALTER", "DATABASE", MatchAny, "SET", "TABLESPACE"))
2347 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2348
2349 /* ALTER EVENT TRIGGER */
2350 else if (Matches("ALTER", "EVENT", "TRIGGER"))
2351 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2352
2353 /* ALTER EVENT TRIGGER <name> */
2354 else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny))
2355 COMPLETE_WITH("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
2356
2357 /* ALTER EVENT TRIGGER <name> ENABLE */
2358 else if (Matches("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
2359 COMPLETE_WITH("REPLICA", "ALWAYS");
2360
2361 /* ALTER EXTENSION <name> */
2362 else if (Matches("ALTER", "EXTENSION", MatchAny))
2363 COMPLETE_WITH("ADD", "DROP", "UPDATE", "SET SCHEMA");
2364
2365 /* ALTER EXTENSION <name> ADD|DROP */
2366 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP"))
2367 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
2368 "CONVERSION", "DOMAIN", "EVENT TRIGGER", "FOREIGN",
2369 "FUNCTION", "MATERIALIZED VIEW", "OPERATOR",
2370 "LANGUAGE", "PROCEDURE", "ROUTINE", "SCHEMA",
2371 "SEQUENCE", "SERVER", "TABLE", "TEXT SEARCH",
2372 "TRANSFORM FOR", "TYPE", "VIEW");
2373
2374 /* ALTER EXTENSION <name> ADD|DROP FOREIGN */
2375 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "FOREIGN"))
2376 COMPLETE_WITH("DATA WRAPPER", "TABLE");
2377
2378 /* ALTER EXTENSION <name> ADD|DROP OPERATOR */
2379 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "OPERATOR"))
2380 COMPLETE_WITH("CLASS", "FAMILY");
2381
2382 /* ALTER EXTENSION <name> ADD|DROP TEXT SEARCH */
2383 else if (Matches("ALTER", "EXTENSION", MatchAny, "ADD|DROP", "TEXT", "SEARCH"))
2384 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2385
2386 /* ALTER EXTENSION <name> UPDATE */
2387 else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE"))
2388 COMPLETE_WITH("TO");
2389
2390 /* ALTER EXTENSION <name> UPDATE TO */
2391 else if (Matches("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
2392 {
2393 set_completion_reference(prev3_wd);
2394 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2395 }
2396
2397 /* ALTER FOREIGN */
2398 else if (Matches("ALTER", "FOREIGN"))
2399 COMPLETE_WITH("DATA WRAPPER", "TABLE");
2400
2401 /* ALTER FOREIGN DATA WRAPPER <name> */
2402 else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2403 COMPLETE_WITH("HANDLER", "VALIDATOR", "NO",
2404 "OPTIONS", "OWNER TO", "RENAME TO");
2405 else if (Matches("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny, "NO"))
2406 COMPLETE_WITH("HANDLER", "VALIDATOR");
2407
2408 /* ALTER FOREIGN TABLE <name> */
2409 else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny))
2410 COMPLETE_WITH("ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE",
2411 "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO",
2412 "RENAME", "SET", "VALIDATE CONSTRAINT");
2413
2414 /* ALTER INDEX */
2415 else if (Matches("ALTER", "INDEX"))
2416 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
2417 "ALL IN TABLESPACE");
2418 /* ALTER INDEX <name> */
2419 else if (Matches("ALTER", "INDEX", MatchAny))
2420 COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
2421 "RESET", "ATTACH PARTITION",
2422 "DEPENDS ON EXTENSION", "NO DEPENDS ON EXTENSION");
2423 else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH"))
2424 COMPLETE_WITH("PARTITION");
2425 else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
2426 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
2427 /* ALTER INDEX <name> ALTER */
2428 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER"))
2429 COMPLETE_WITH("COLUMN");
2430 /* ALTER INDEX <name> ALTER COLUMN */
2431 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN"))
2432 {
2433 set_completion_reference(prev3_wd);
2434 COMPLETE_WITH_SCHEMA_QUERY_VERBATIM(Query_for_list_of_attribute_numbers);
2435 }
2436 /* ALTER INDEX <name> ALTER COLUMN <colnum> */
2437 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
2438 COMPLETE_WITH("SET STATISTICS");
2439 /* ALTER INDEX <name> ALTER COLUMN <colnum> SET */
2440 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET"))
2441 COMPLETE_WITH("STATISTICS");
2442 /* ALTER INDEX <name> ALTER COLUMN <colnum> SET STATISTICS */
2443 else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS"))
2444 {
2445 /* Enforce no completion here, as an integer has to be specified */
2446 }
2447 /* ALTER INDEX <name> SET */
2448 else if (Matches("ALTER", "INDEX", MatchAny, "SET"))
2449 COMPLETE_WITH("(", "TABLESPACE");
2450 /* ALTER INDEX <name> RESET */
2451 else if (Matches("ALTER", "INDEX", MatchAny, "RESET"))
2452 COMPLETE_WITH("(");
2453 /* ALTER INDEX <foo> SET|RESET ( */
2454 else if (Matches("ALTER", "INDEX", MatchAny, "RESET", "("))
2455 COMPLETE_WITH("fillfactor",
2456 "deduplicate_items", /* BTREE */
2457 "fastupdate", "gin_pending_list_limit", /* GIN */
2458 "buffering", /* GiST */
2459 "pages_per_range", "autosummarize" /* BRIN */
2460 );
2461 else if (Matches("ALTER", "INDEX", MatchAny, "SET", "("))
2462 COMPLETE_WITH("fillfactor =",
2463 "deduplicate_items =", /* BTREE */
2464 "fastupdate =", "gin_pending_list_limit =", /* GIN */
2465 "buffering =", /* GiST */
2466 "pages_per_range =", "autosummarize =" /* BRIN */
2467 );
2468 else if (Matches("ALTER", "INDEX", MatchAny, "NO", "DEPENDS"))
2469 COMPLETE_WITH("ON EXTENSION");
2470 else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS"))
2471 COMPLETE_WITH("ON EXTENSION");
2472
2473 /* ALTER LANGUAGE <name> */
2474 else if (Matches("ALTER", "LANGUAGE", MatchAny))
2475 COMPLETE_WITH("OWNER TO", "RENAME TO");
2476
2477 /* ALTER LARGE OBJECT <oid> */
2478 else if (Matches("ALTER", "LARGE", "OBJECT", MatchAny))
2479 COMPLETE_WITH("OWNER TO");
2480
2481 /* ALTER MATERIALIZED VIEW */
2482 else if (Matches("ALTER", "MATERIALIZED", "VIEW"))
2483 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_matviews,
2484 "ALL IN TABLESPACE");
2485
2486 /* ALTER USER,ROLE <name> */
2487 else if (Matches("ALTER", "USER|ROLE", MatchAny) &&
2488 !TailMatches("USER", "MAPPING"))
2489 COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2490 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
2491 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2492 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2493 "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
2494 "VALID UNTIL", "WITH");
2495
2496 /* ALTER USER,ROLE <name> RESET */
2497 else if (Matches("ALTER", "USER|ROLE", MatchAny, "RESET"))
2498 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_user_vars, "ALL");
2499
2500 /* ALTER USER,ROLE <name> WITH */
2501 else if (Matches("ALTER", "USER|ROLE", MatchAny, "WITH"))
2502 /* Similar to the above, but don't complete "WITH" again. */
2503 COMPLETE_WITH("BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2504 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
2505 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2506 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2507 "RENAME TO", "REPLICATION", "RESET", "SET", "SUPERUSER",
2508 "VALID UNTIL");
2509
2510 /* ALTER DEFAULT PRIVILEGES */
2511 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES"))
2512 COMPLETE_WITH("FOR", "GRANT", "IN SCHEMA", "REVOKE");
2513 /* ALTER DEFAULT PRIVILEGES FOR */
2514 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
2515 COMPLETE_WITH("ROLE");
2516 /* ALTER DEFAULT PRIVILEGES IN */
2517 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
2518 COMPLETE_WITH("SCHEMA");
2519 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
2520 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2521 MatchAny))
2522 COMPLETE_WITH("GRANT", "REVOKE", "IN SCHEMA");
2523 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
2524 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2525 MatchAny))
2526 COMPLETE_WITH("GRANT", "REVOKE", "FOR ROLE");
2527 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
2528 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2529 MatchAny, "FOR"))
2530 COMPLETE_WITH("ROLE");
2531 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
2532 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
2533 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
2534 MatchAny, "IN", "SCHEMA", MatchAny) ||
2535 Matches("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
2536 MatchAny, "FOR", "ROLE|USER", MatchAny))
2537 COMPLETE_WITH("GRANT", "REVOKE");
2538 /* ALTER DOMAIN <name> */
2539 else if (Matches("ALTER", "DOMAIN", MatchAny))
2540 COMPLETE_WITH("ADD", "DROP", "OWNER TO", "RENAME", "SET",
2541 "VALIDATE CONSTRAINT");
2542 /* ALTER DOMAIN <sth> DROP */
2543 else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP"))
2544 COMPLETE_WITH("CONSTRAINT", "DEFAULT", "NOT NULL");
2545 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
2546 else if (Matches("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
2547 {
2548 set_completion_reference(prev3_wd);
2549 COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_type);
2550 }
2551 /* ALTER DOMAIN <sth> RENAME */
2552 else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME"))
2553 COMPLETE_WITH("CONSTRAINT", "TO");
2554 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
2555 else if (Matches("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
2556 COMPLETE_WITH("TO");
2557
2558 /* ALTER DOMAIN <sth> SET */
2559 else if (Matches("ALTER", "DOMAIN", MatchAny, "SET"))
2560 COMPLETE_WITH("DEFAULT", "NOT NULL", "SCHEMA");
2561 /* ALTER SEQUENCE <name> */
2562 else if (Matches("ALTER", "SEQUENCE", MatchAny))
2563 COMPLETE_WITH("AS", "INCREMENT", "MINVALUE", "MAXVALUE", "RESTART",
2564 "START", "NO", "CACHE", "CYCLE", "SET", "OWNED BY",
2565 "OWNER TO", "RENAME TO");
2566 /* ALTER SEQUENCE <name> AS */
2567 else if (TailMatches("ALTER", "SEQUENCE", MatchAny, "AS"))
2568 COMPLETE_WITH_CS("smallint", "integer", "bigint");
2569 /* ALTER SEQUENCE <name> NO */
2570 else if (Matches("ALTER", "SEQUENCE", MatchAny, "NO"))
2571 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
2572 /* ALTER SEQUENCE <name> SET */
2573 else if (Matches("ALTER", "SEQUENCE", MatchAny, "SET"))
2574 COMPLETE_WITH("SCHEMA", "LOGGED", "UNLOGGED");
2575 /* ALTER SERVER <name> */
2576 else if (Matches("ALTER", "SERVER", MatchAny))
2577 COMPLETE_WITH("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
2578 /* ALTER SERVER <name> VERSION <version> */
2579 else if (Matches("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
2580 COMPLETE_WITH("OPTIONS");
2581 /* ALTER SYSTEM SET, RESET, RESET ALL */
2582 else if (Matches("ALTER", "SYSTEM"))
2583 COMPLETE_WITH("SET", "RESET");
2584 else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
2585 COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_alter_system_set_vars,
2586 "ALL");
2587 else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
2588 COMPLETE_WITH("TO");
2589 /* ALTER VIEW <name> */
2590 else if (Matches("ALTER", "VIEW", MatchAny))
2591 COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME", "RESET", "SET");
2592 /* ALTER VIEW xxx RENAME */
2593 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME"))
2594 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
2595 else if (Matches("ALTER", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
2596 COMPLETE_WITH_ATTR(prev3_wd);
2597 /* ALTER VIEW xxx ALTER [ COLUMN ] yyy */
2598 else if (Matches("ALTER", "VIEW", MatchAny, "ALTER", MatchAny) ||
2599 Matches("ALTER", "VIEW", MatchAny, "ALTER", "COLUMN", MatchAny))
2600 COMPLETE_WITH("SET DEFAULT", "DROP DEFAULT");
2601 /* ALTER VIEW xxx RENAME yyy */
2602 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
2603 COMPLETE_WITH("TO");
2604 /* ALTER VIEW xxx RENAME COLUMN yyy */
2605 else if (Matches("ALTER", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
2606 COMPLETE_WITH("TO");
2607 /* ALTER VIEW xxx RESET ( */
2608 else if (Matches("ALTER", "VIEW", MatchAny, "RESET"))
2609 COMPLETE_WITH("(");
2610 /* Complete ALTER VIEW xxx SET with "(" or "SCHEMA" */
2611 else if (Matches("ALTER", "VIEW", MatchAny, "SET"))
2612 COMPLETE_WITH("(", "SCHEMA");
2613 /* ALTER VIEW xxx SET|RESET ( yyy [= zzz] ) */
2614 else if (Matches("ALTER", "VIEW", MatchAny, "SET|RESET", "("))
2615 COMPLETE_WITH_LIST(view_optional_parameters);
2616 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", MatchAny))
2617 COMPLETE_WITH("=");
2618 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "check_option", "="))
2619 COMPLETE_WITH("local", "cascaded");
2620 else if (Matches("ALTER", "VIEW", MatchAny, "SET", "(", "security_barrier|security_invoker", "="))
2621 COMPLETE_WITH("true", "false");
2622
2623 /* ALTER MATERIALIZED VIEW <name> */
2624 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny))
2625 COMPLETE_WITH("ALTER COLUMN", "CLUSTER ON", "DEPENDS ON EXTENSION",
2626 "NO DEPENDS ON EXTENSION", "OWNER TO", "RENAME",
2627 "RESET (", "SET");
2628 /* ALTER MATERIALIZED VIEW xxx RENAME */
2629 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME"))
2630 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "TO");
2631 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "ALTER|RENAME", "COLUMN"))
2632 COMPLETE_WITH_ATTR(prev3_wd);
2633 /* ALTER MATERIALIZED VIEW xxx RENAME yyy */
2634 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", MatchAnyExcept("TO")))
2635 COMPLETE_WITH("TO");
2636 /* ALTER MATERIALIZED VIEW xxx RENAME COLUMN yyy */
2637 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "RENAME", "COLUMN", MatchAnyExcept("TO")))
2638 COMPLETE_WITH("TO");
2639 /* ALTER MATERIALIZED VIEW xxx SET */
2640 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET"))
2641 COMPLETE_WITH("(", "ACCESS METHOD", "SCHEMA", "TABLESPACE", "WITHOUT CLUSTER");
2642 /* ALTER MATERIALIZED VIEW xxx SET ACCESS METHOD */
2643 else if (Matches("ALTER", "MATERIALIZED", "VIEW", MatchAny, "SET", "ACCESS", "METHOD"))
2644 COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
2645
2646 /* ALTER POLICY <name> */
2647 else if (Matches("ALTER", "POLICY"))
2648 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2649 /* ALTER POLICY <name> ON */
2650 else if (Matches("ALTER", "POLICY", MatchAny))
2651 COMPLETE_WITH("ON");
2652 /* ALTER POLICY <name> ON <table> */
2653 else if (Matches("ALTER", "POLICY", MatchAny, "ON"))
2654 {
2655 set_completion_reference(prev2_wd);
2656 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
2657 }
2658 /* ALTER POLICY <name> ON <table> - show options */
2659 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny))
2660 COMPLETE_WITH("RENAME TO", "TO", "USING (", "WITH CHECK (");
2661 /* ALTER POLICY <name> ON <table> TO <role> */
2662 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2663 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
2664 Keywords_for_list_of_grant_roles);
2665 /* ALTER POLICY <name> ON <table> USING ( */
2666 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2667 COMPLETE_WITH("(");
2668 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
2669 else if (Matches("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
2670 COMPLETE_WITH("(");
2671
2672 /* ALTER RULE <name>, add ON */
2673 else if (Matches("ALTER", "RULE", MatchAny))
2674 COMPLETE_WITH("ON");
2675
2676 /* If we have ALTER RULE <name> ON, then add the correct tablename */
2677 else if (Matches("ALTER", "RULE", MatchAny, "ON"))
2678 {
2679 set_completion_reference(prev2_wd);
2680 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
2681 }
2682
2683 /* ALTER RULE <name> ON <name> */
2684 else if (Matches("ALTER", "RULE", MatchAny, "ON", MatchAny))
2685 COMPLETE_WITH("RENAME TO");
2686
2687 /* ALTER STATISTICS <name> */
2688 else if (Matches("ALTER", "STATISTICS", MatchAny))
2689 COMPLETE_WITH("OWNER TO", "RENAME TO", "SET SCHEMA", "SET STATISTICS");
2690 /* ALTER STATISTICS <name> SET */
2691 else if (Matches("ALTER", "STATISTICS", MatchAny, "SET"))
2692 COMPLETE_WITH("SCHEMA", "STATISTICS");
2693
2694 /* ALTER TRIGGER <name>, add ON */
2695 else if (Matches("ALTER", "TRIGGER", MatchAny))
2696 COMPLETE_WITH("ON");
2697
2698 else if (Matches("ALTER", "TRIGGER", MatchAny, "ON"))
2699 {
2700 set_completion_reference(prev2_wd);
2701 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
2702 }
2703
2704 /* ALTER TRIGGER <name> ON <name> */
2705 else if (Matches("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
2706 COMPLETE_WITH("RENAME TO", "DEPENDS ON EXTENSION",
2707 "NO DEPENDS ON EXTENSION");
2708
2709 /*
2710 * If we detect ALTER TABLE <name>, suggest sub commands
2711 */
2712 else if (Matches("ALTER", "TABLE", MatchAny))
2713 COMPLETE_WITH("ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP",
2714 "ENABLE", "INHERIT", "NO", "RENAME", "RESET",
2715 "OWNER TO", "SET", "VALIDATE CONSTRAINT",
2716 "REPLICA IDENTITY", "ATTACH PARTITION",
2717 "DETACH PARTITION", "FORCE ROW LEVEL SECURITY",
2718 "OF", "NOT OF");
2719 /* ALTER TABLE xxx ADD */
2720 else if (Matches("ALTER", "TABLE", MatchAny, "ADD"))
2721 {
2722 /* make sure to keep this list and the !Matches() below in sync */
2723 COMPLETE_WITH("COLUMN", "CONSTRAINT", "CHECK", "UNIQUE", "PRIMARY KEY",
2724 "EXCLUDE", "FOREIGN KEY");
2725 }
2726 /* ALTER TABLE xxx ADD [COLUMN] yyy */
2727 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "COLUMN", MatchAny) ||
2728 Matches("ALTER", "TABLE", MatchAny, "ADD", MatchAnyExcept("COLUMN|CONSTRAINT|CHECK|UNIQUE|PRIMARY|EXCLUDE|FOREIGN")))
2729 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
2730 /* ALTER TABLE xxx ADD CONSTRAINT yyy */
2731 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny))
2732 COMPLETE_WITH("CHECK", "UNIQUE", "PRIMARY KEY", "EXCLUDE", "FOREIGN KEY");
2733 /* ALTER TABLE xxx ADD [CONSTRAINT yyy] (PRIMARY KEY|UNIQUE) */
2734 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY") ||
2735 Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE") ||
2736 Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "PRIMARY", "KEY") ||
2737 Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny, "UNIQUE"))
2738 COMPLETE_WITH("(", "USING INDEX");
2739 /* ALTER TABLE xxx ADD PRIMARY KEY USING INDEX */
2740 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "PRIMARY", "KEY", "USING", "INDEX"))
2741 {
2742 set_completion_reference(prev6_wd);
2743 COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
2744 }
2745 /* ALTER TABLE xxx ADD UNIQUE USING INDEX */
2746 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "UNIQUE", "USING", "INDEX"))
2747 {
2748 set_completion_reference(prev5_wd);
2749 COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
2750 }
2751 /* ALTER TABLE xxx ADD CONSTRAINT yyy PRIMARY KEY USING INDEX */
2752 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2753 "PRIMARY", "KEY", "USING", "INDEX"))
2754 {
2755 set_completion_reference(prev8_wd);
2756 COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
2757 }
2758 /* ALTER TABLE xxx ADD CONSTRAINT yyy UNIQUE USING INDEX */
2759 else if (Matches("ALTER", "TABLE", MatchAny, "ADD", "CONSTRAINT", MatchAny,
2760 "UNIQUE", "USING", "INDEX"))
2761 {
2762 set_completion_reference(prev7_wd);
2763 COMPLETE_WITH_SCHEMA_QUERY(Query_for_unique_index_of_table);
2764 }
2765 /* ALTER TABLE xxx ENABLE */
2766 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE"))
2767 COMPLETE_WITH("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
2768 "TRIGGER");
2769 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
2770 COMPLETE_WITH("RULE", "TRIGGER");
2771 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
2772 {
2773 set_completion_reference(prev3_wd);
2774 COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
2775 }
2776 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
2777 {
2778 set_completion_reference(prev4_wd);
2779 COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
2780 }
2781 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
2782 {
2783 set_completion_reference(prev3_wd);
2784 COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
2785 }
2786 else if (Matches("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
2787 {
2788 set_completion_reference(prev4_wd);
2789 COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
2790 }
2791 /* ALTER TABLE xxx INHERIT */
2792 else if (Matches("ALTER", "TABLE", MatchAny, "INHERIT"))
2793 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2794 /* ALTER TABLE xxx NO */
2795 else if (Matches("ALTER", "TABLE", MatchAny, "NO"))
2796 COMPLETE_WITH("FORCE ROW LEVEL SECURITY", "INHERIT");
2797 /* ALTER TABLE xxx NO INHERIT */
2798 else if (Matches("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
2799 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2800 /* ALTER TABLE xxx DISABLE */
2801 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE"))
2802 COMPLETE_WITH("ROW LEVEL SECURITY", "RULE", "TRIGGER");
2803 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
2804 {
2805 set_completion_reference(prev3_wd);
2806 COMPLETE_WITH_SCHEMA_QUERY(Query_for_rule_of_table);
2807 }
2808 else if (Matches("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
2809 {
2810 set_completion_reference(prev3_wd);
2811 COMPLETE_WITH_SCHEMA_QUERY(Query_for_trigger_of_table);
2812 }
2813
2814 /* ALTER TABLE xxx ALTER */
2815 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER"))
2816 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT");
2817
2818 /* ALTER TABLE xxx RENAME */
2819 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME"))
2820 COMPLETE_WITH_ATTR_PLUS(prev2_wd, "COLUMN", "CONSTRAINT", "TO");
2821 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
2822 COMPLETE_WITH_ATTR(prev3_wd);
2823
2824 /* ALTER TABLE xxx RENAME yyy */
2825 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
2826 COMPLETE_WITH("TO");
2827
2828 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
2829 else if (Matches("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
2830 COMPLETE_WITH("TO");
2831
2832 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
2833 else if (Matches("ALTER", "TABLE", MatchAny, "DROP"))
2834 COMPLETE_WITH("COLUMN", "CONSTRAINT");
2835 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
2836 else if (Matches("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
2837 COMPLETE_WITH_ATTR(prev3_wd);
2838 /* ALTER TABLE <sth> ALTER|DROP|RENAME CONSTRAINT <constraint> */
2839 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME", "CONSTRAINT"))
2840 {
2841 set_completion_reference(prev3_wd);
2842 COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_table);
2843 }
2844 /* ALTER TABLE <sth> VALIDATE CONSTRAINT <non-validated constraint> */
2845 else if (Matches("ALTER", "TABLE", MatchAny, "VALIDATE", "CONSTRAINT"))
2846 {
2847 set_completion_reference(prev3_wd);
2848 COMPLETE_WITH_SCHEMA_QUERY(Query_for_constraint_of_table_not_validated);
2849 }
2850 /* ALTER TABLE ALTER [COLUMN] <foo> */
2851 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
2852 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
2853 COMPLETE_WITH("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
2854 /* ALTER TABLE ALTER [COLUMN] <foo> ADD */
2855 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD") ||
2856 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD"))
2857 COMPLETE_WITH("GENERATED");
2858 /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
2859 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED") ||
2860 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED"))
2861 COMPLETE_WITH("ALWAYS", "BY DEFAULT");
2862 /* ALTER TABLE ALTER [COLUMN] <foo> ADD GENERATED */
2863 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2864 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "ALWAYS") ||
2865 Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT") ||
2866 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "ADD", "GENERATED", "BY", "DEFAULT"))
2867 COMPLETE_WITH("AS IDENTITY");
2868 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
2869 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
2870 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
2871 COMPLETE_WITH("(", "COMPRESSION", "DATA TYPE", "DEFAULT", "EXPRESSION", "GENERATED", "NOT NULL",
2872 "STATISTICS", "STORAGE",
2873 /* a subset of ALTER SEQUENCE options */
2874 "INCREMENT", "MINVALUE", "MAXVALUE", "START", "NO", "CACHE", "CYCLE");
2875 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
2876 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
2877 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
2878 COMPLETE_WITH("n_distinct", "n_distinct_inherited");
2879 /* ALTER TABLE ALTER [COLUMN] <foo> SET COMPRESSION */
2880 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "COMPRESSION") ||
2881 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "COMPRESSION"))
2882 COMPLETE_WITH("DEFAULT", "PGLZ", "LZ4");
2883 /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION */
2884 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION") ||
2885 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION"))
2886 COMPLETE_WITH("AS");
2887 /* ALTER TABLE ALTER [COLUMN] <foo> SET EXPRESSION AS */
2888 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "EXPRESSION", "AS") ||
2889 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "EXPRESSION", "AS"))
2890 COMPLETE_WITH("(");
2891 /* ALTER TABLE ALTER [COLUMN] <foo> SET GENERATED */
2892 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "GENERATED") ||
2893 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "GENERATED"))
2894 COMPLETE_WITH("ALWAYS", "BY DEFAULT");
2895 /* ALTER TABLE ALTER [COLUMN] <foo> SET NO */
2896 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "NO") ||
2897 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "NO"))
2898 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
2899 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
2900 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
2901 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
2902 COMPLETE_WITH("DEFAULT", "PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
2903 /* ALTER TABLE ALTER [COLUMN] <foo> SET STATISTICS */
2904 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STATISTICS") ||
2905 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STATISTICS"))
2906 {
2907 /* Enforce no completion here, as an integer has to be specified */
2908 }
2909 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
2910 else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
2911 Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
2912 COMPLETE_WITH("DEFAULT", "EXPRESSION", "IDENTITY", "NOT NULL");
2913 else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER"))
2914 COMPLETE_WITH("ON");
2915 else if (Matches("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
2916 {
2917 set_completion_reference(prev3_wd);
2918 COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
2919 }
2920 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
2921 else if (Matches("ALTER", "TABLE", MatchAny, "SET"))
2922 COMPLETE_WITH("(", "ACCESS METHOD", "LOGGED", "SCHEMA",
2923 "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT");
2924
2925 /*
2926 * If we have ALTER TABLE <sth> SET ACCESS METHOD provide a list of table
2927 * AMs.
2928 */
2929 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "ACCESS", "METHOD"))
2930 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_table_access_methods,
2931 "DEFAULT");
2932
2933 /*
2934 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
2935 * tablespaces
2936 */
2937 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
2938 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2939 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
2940 else if (Matches("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
2941 COMPLETE_WITH("CLUSTER", "OIDS");
2942 /* ALTER TABLE <foo> RESET */
2943 else if (Matches("ALTER", "TABLE", MatchAny, "RESET"))
2944 COMPLETE_WITH("(");
2945 /* ALTER TABLE <foo> SET|RESET ( */
2946 else if (Matches("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
2947 COMPLETE_WITH_LIST(table_storage_parameters);
2948 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
2949 {
2950 set_completion_reference(prev5_wd);
2951 COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
2952 }
2953 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
2954 COMPLETE_WITH("INDEX");
2955 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
2956 COMPLETE_WITH("FULL", "NOTHING", "DEFAULT", "USING");
2957 else if (Matches("ALTER", "TABLE", MatchAny, "REPLICA"))
2958 COMPLETE_WITH("IDENTITY");
2959
2960 /*
2961 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
2962 * tables.
2963 */
2964 else if (Matches("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
2965 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
2966 /* Limited completion support for partition bound specification */
2967 else if (TailMatches("ATTACH", "PARTITION", MatchAny))
2968 COMPLETE_WITH("FOR VALUES", "DEFAULT");
2969 else if (TailMatches("FOR", "VALUES"))
2970 COMPLETE_WITH("FROM (", "IN (", "WITH (");
2971
2972 /*
2973 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
2974 * partitions of <foo>.
2975 */
2976 else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
2977 {
2978 set_completion_reference(prev3_wd);
2979 COMPLETE_WITH_SCHEMA_QUERY(Query_for_partition_of_table);
2980 }
2981 else if (Matches("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION", MatchAny))
2982 COMPLETE_WITH("CONCURRENTLY", "FINALIZE");
2983
2984 /* ALTER TABLE <name> OF */
2985 else if (Matches("ALTER", "TABLE", MatchAny, "OF"))
2986 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_composite_datatypes);
2987
2988 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
2989 else if (Matches("ALTER", "TABLESPACE", MatchAny))
2990 COMPLETE_WITH("RENAME TO", "OWNER TO", "SET", "RESET");
2991 /* ALTER TABLESPACE <foo> SET|RESET */
2992 else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
2993 COMPLETE_WITH("(");
2994 /* ALTER TABLESPACE <foo> SET|RESET ( */
2995 else if (Matches("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
2996 COMPLETE_WITH("seq_page_cost", "random_page_cost",
2997 "effective_io_concurrency", "maintenance_io_concurrency");
2998
2999 /* ALTER TEXT SEARCH */
3000 else if (Matches("ALTER", "TEXT", "SEARCH"))
3001 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3002 else if (Matches("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
3003 COMPLETE_WITH("RENAME TO", "SET SCHEMA");
3004 else if (Matches("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
3005 COMPLETE_WITH("(", "OWNER TO", "RENAME TO", "SET SCHEMA");
3006 else if (Matches("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
3007 COMPLETE_WITH("ADD MAPPING FOR", "ALTER MAPPING",
3008 "DROP MAPPING FOR",
3009 "OWNER TO", "RENAME TO", "SET SCHEMA");
3010
3011 /* complete ALTER TYPE <foo> with actions */
3012 else if (Matches("ALTER", "TYPE", MatchAny))
3013 COMPLETE_WITH("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
3014 "DROP ATTRIBUTE",
3015 "OWNER TO", "RENAME", "SET SCHEMA", "SET (");
3016 /* complete ALTER TYPE <foo> ADD with actions */
3017 else if (Matches("ALTER", "TYPE", MatchAny, "ADD"))
3018 COMPLETE_WITH("ATTRIBUTE", "VALUE");
3019 /* ALTER TYPE <foo> RENAME */
3020 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME"))
3021 COMPLETE_WITH("ATTRIBUTE", "TO", "VALUE");
3022 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
3023 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
3024 COMPLETE_WITH("TO");
3025 /* ALTER TYPE xxx RENAME ATTRIBUTE yyy TO zzz */
3026 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny, "TO", MatchAny))
3027 COMPLETE_WITH("CASCADE", "RESTRICT");
3028
3029 /*
3030 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
3031 * of attributes
3032 */
3033 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
3034 COMPLETE_WITH_ATTR(prev3_wd);
3035 /* complete ALTER TYPE ADD ATTRIBUTE <foo> with list of types */
3036 else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny))
3037 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
3038 /* complete ALTER TYPE ADD ATTRIBUTE <foo> <footype> with CASCADE/RESTRICT */
3039 else if (Matches("ALTER", "TYPE", MatchAny, "ADD", "ATTRIBUTE", MatchAny, MatchAny))
3040 COMPLETE_WITH("CASCADE", "RESTRICT");
3041 /* complete ALTER TYPE DROP ATTRIBUTE <foo> with CASCADE/RESTRICT */
3042 else if (Matches("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE", MatchAny))
3043 COMPLETE_WITH("CASCADE", "RESTRICT");
3044 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
3045 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
3046 COMPLETE_WITH("TYPE");
3047 /* ALTER TYPE ALTER ATTRIBUTE <foo> TYPE <footype> */
3048 else if (Matches("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny, "TYPE", MatchAny))
3049 COMPLETE_WITH("CASCADE", "RESTRICT");
3050 /* complete ALTER TYPE <sth> RENAME VALUE with list of enum values */
3051 else if (Matches("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
3052 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
3053 /* ALTER TYPE <foo> SET */
3054 else if (Matches("ALTER", "TYPE", MatchAny, "SET"))
3055 COMPLETE_WITH("(", "SCHEMA");
3056 /* complete ALTER TYPE <foo> SET ( with settable properties */
3057 else if (Matches("ALTER", "TYPE", MatchAny, "SET", "("))
3058 COMPLETE_WITH("ANALYZE", "RECEIVE", "SEND", "STORAGE", "SUBSCRIPT",
3059 "TYPMOD_IN", "TYPMOD_OUT");
3060
3061 /* complete ALTER GROUP <foo> */
3062 else if (Matches("ALTER", "GROUP", MatchAny))
3063 COMPLETE_WITH("ADD USER", "DROP USER", "RENAME TO");
3064 /* complete ALTER GROUP <foo> ADD|DROP with USER */
3065 else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP"))
3066 COMPLETE_WITH("USER");
3067 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
3068 else if (Matches("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
3069 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3070
3071/*
3072 * ANALYZE [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
3073 * ANALYZE [ VERBOSE ] [ [ ONLY ] table_and_columns [, ...] ]
3074 */
3075 else if (Matches("ANALYZE"))
3076 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_analyzables,
3077 "(", "VERBOSE", "ONLY");
3078 else if (Matches("ANALYZE", "VERBOSE"))
3079 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_analyzables,
3080 "ONLY");
3081 else if (HeadMatches("ANALYZE", "(*") &&
3082 !HeadMatches("ANALYZE", "(*)"))
3083 {
3084 /*
3085 * This fires if we're in an unfinished parenthesized option list.
3086 * get_previous_words treats a completed parenthesized option list as
3087 * one word, so the above test is correct.
3088 */
3089 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3090 COMPLETE_WITH("VERBOSE", "SKIP_LOCKED", "BUFFER_USAGE_LIMIT");
3091 else if (TailMatches("VERBOSE|SKIP_LOCKED"))
3092 COMPLETE_WITH("ON", "OFF");
3093 }
3094 else if (Matches("ANALYZE", MatchAnyN, "("))
3095 /* "ANALYZE (" should be caught above, so assume we want columns */
3096 COMPLETE_WITH_ATTR(prev2_wd);
3097 else if (HeadMatches("ANALYZE"))
3098 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_analyzables);
3099
3100/* BEGIN */
3101 else if (Matches("BEGIN"))
3102 COMPLETE_WITH("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3103/* END, ABORT */
3104 else if (Matches("END|ABORT"))
3105 COMPLETE_WITH("AND", "WORK", "TRANSACTION");
3106/* COMMIT */
3107 else if (Matches("COMMIT"))
3108 COMPLETE_WITH("AND", "WORK", "TRANSACTION", "PREPARED");
3109/* RELEASE SAVEPOINT */
3110 else if (Matches("RELEASE"))
3111 COMPLETE_WITH("SAVEPOINT");
3112/* ROLLBACK */
3113 else if (Matches("ROLLBACK"))
3114 COMPLETE_WITH("AND", "WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
3115 else if (Matches("ABORT|END|COMMIT|ROLLBACK", "AND"))
3116 COMPLETE_WITH("CHAIN");
3117/* CALL */
3118 else if (Matches("CALL"))
3119 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures);
3120 else if (Matches("CALL", MatchAny))
3121 COMPLETE_WITH("(");
3122/* CLOSE */
3123 else if (Matches("CLOSE"))
3124 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
3125 "ALL");
3126/* CLUSTER */
3127 else if (Matches("CLUSTER"))
3128 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_clusterables,
3129 "VERBOSE");
3130 else if (Matches("CLUSTER", "VERBOSE") ||
3131 Matches("CLUSTER", "(*)"))
3132 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_clusterables);
3133 /* If we have CLUSTER <sth>, then add "USING" */
3134 else if (Matches("CLUSTER", MatchAnyExcept("VERBOSE|ON|(|(*)")))
3135 COMPLETE_WITH("USING");
3136 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
3137 else if (Matches("CLUSTER", "VERBOSE|(*)", MatchAny))
3138 COMPLETE_WITH("USING");
3139 /* If we have CLUSTER <sth> USING, then add the index as well */
3140 else if (Matches("CLUSTER", MatchAny, "USING") ||
3141 Matches("CLUSTER", "VERBOSE|(*)", MatchAny, "USING"))
3142 {
3143 set_completion_reference(prev2_wd);
3144 COMPLETE_WITH_SCHEMA_QUERY(Query_for_index_of_table);
3145 }
3146 else if (HeadMatches("CLUSTER", "(*") &&
3147 !HeadMatches("CLUSTER", "(*)"))
3148 {
3149 /*
3150 * This fires if we're in an unfinished parenthesized option list.
3151 * get_previous_words treats a completed parenthesized option list as
3152 * one word, so the above test is correct.
3153 */
3154 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
3155 COMPLETE_WITH("VERBOSE");
3156 }
3157
3158/* COMMENT */
3159 else if (Matches("COMMENT"))
3160 COMPLETE_WITH("ON");
3161 else if (Matches("COMMENT", "ON"))
3162 COMPLETE_WITH("ACCESS METHOD", "AGGREGATE", "CAST", "COLLATION",
3163 "COLUMN", "CONSTRAINT", "CONVERSION", "DATABASE",
3164 "DOMAIN", "EXTENSION", "EVENT TRIGGER",
3165 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
3166 "FUNCTION", "INDEX", "LANGUAGE", "LARGE OBJECT",
3167 "MATERIALIZED VIEW", "OPERATOR", "POLICY",
3168 "PROCEDURE", "PROCEDURAL LANGUAGE", "PUBLICATION", "ROLE",
3169 "ROUTINE", "RULE", "SCHEMA", "SEQUENCE", "SERVER",
3170 "STATISTICS", "SUBSCRIPTION", "TABLE",
3171 "TABLESPACE", "TEXT SEARCH", "TRANSFORM FOR",
3172 "TRIGGER", "TYPE", "VIEW");
3173 else if (Matches("COMMENT", "ON", "ACCESS", "METHOD"))
3174 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3175 else if (Matches("COMMENT", "ON", "CONSTRAINT"))
3176 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
3177 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny))
3178 COMPLETE_WITH("ON");
3179 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
3180 {
3181 set_completion_reference(prev2_wd);
3182 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables_for_constraint,
3183 "DOMAIN");
3184 }
3185 else if (Matches("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON", "DOMAIN"))
3186 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
3187 else if (Matches("COMMENT", "ON", "EVENT", "TRIGGER"))
3188 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3189 else if (Matches("COMMENT", "ON", "FOREIGN"))
3190 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3191 else if (Matches("COMMENT", "ON", "FOREIGN", "TABLE"))
3192 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
3193 else if (Matches("COMMENT", "ON", "MATERIALIZED", "VIEW"))
3194 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
3195 else if (Matches("COMMENT", "ON", "POLICY"))
3196 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
3197 else if (Matches("COMMENT", "ON", "POLICY", MatchAny))
3198 COMPLETE_WITH("ON");
3199 else if (Matches("COMMENT", "ON", "POLICY", MatchAny, "ON"))
3200 {
3201 set_completion_reference(prev2_wd);
3202 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
3203 }
3204 else if (Matches("COMMENT", "ON", "PROCEDURAL", "LANGUAGE"))
3205 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3206 else if (Matches("COMMENT", "ON", "RULE", MatchAny))
3207 COMPLETE_WITH("ON");
3208 else if (Matches("COMMENT", "ON", "RULE", MatchAny, "ON"))
3209 {
3210 set_completion_reference(prev2_wd);
3211 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
3212 }
3213 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH"))
3214 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3215 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "CONFIGURATION"))
3216 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_configurations);
3217 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "DICTIONARY"))
3218 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_dictionaries);
3219 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "PARSER"))
3220 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_parsers);
3221 else if (Matches("COMMENT", "ON", "TEXT", "SEARCH", "TEMPLATE"))
3222 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_templates);
3223 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR"))
3224 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
3225 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny))
3226 COMPLETE_WITH("LANGUAGE");
3227 else if (Matches("COMMENT", "ON", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3228 {
3229 set_completion_reference(prev2_wd);
3230 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3231 }
3232 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny))
3233 COMPLETE_WITH("ON");
3234 else if (Matches("COMMENT", "ON", "TRIGGER", MatchAny, "ON"))
3235 {
3236 set_completion_reference(prev2_wd);
3237 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
3238 }
3239 else if (Matches("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
3240 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3241 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")) ||
3242 Matches("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
3243 COMPLETE_WITH("IS");
3244
3245/* COPY */
3246
3247 /*
3248 * If we have COPY, offer list of tables or "(" (Also cover the analogous
3249 * backslash command).
3250 */
3251 else if (Matches("COPY|\\copy"))
3252 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables, "(");
3253 /* Complete COPY ( with legal query commands */
3254 else if (Matches("COPY|\\copy", "("))
3255 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT INTO", "UPDATE", "DELETE FROM", "MERGE INTO", "WITH");
3256 /* Complete COPY <sth> */
3257 else if (Matches("COPY|\\copy", MatchAny))
3258 COMPLETE_WITH("FROM", "TO");
3259 /* Complete COPY <sth> FROM|TO with filename */
3260 else if (Matches("COPY", MatchAny, "FROM|TO"))
3261 {
3262 completion_charp = "";
3263 completion_force_quote = true; /* COPY requires quoted filename */
3264 matches = rl_completion_matches(text, complete_from_files);
3265 }
3266 else if (Matches("\\copy", MatchAny, "FROM|TO"))
3267 {
3268 completion_charp = "";
3269 completion_force_quote = false;
3270 matches = rl_completion_matches(text, complete_from_files);
3271 }
3272
3273 /* Complete COPY <sth> TO <sth> */
3274 else if (Matches("COPY|\\copy", MatchAny, "TO", MatchAny))
3275 COMPLETE_WITH("WITH (");
3276
3277 /* Complete COPY <sth> FROM <sth> */
3278 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny))
3279 COMPLETE_WITH("WITH (", "WHERE");
3280
3281 /* Complete COPY <sth> FROM|TO filename WITH ( */
3282 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "("))
3283 COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL",
3284 "HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE",
3285 "FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT",
3286 "ON_ERROR", "LOG_VERBOSITY");
3287
3288 /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
3289 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "FORMAT"))
3290 COMPLETE_WITH("binary", "csv", "text");
3291
3292 /* Complete COPY <sth> FROM filename WITH (ON_ERROR */
3293 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "ON_ERROR"))
3294 COMPLETE_WITH("stop", "ignore");
3295
3296 /* Complete COPY <sth> FROM filename WITH (LOG_VERBOSITY */
3297 else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "LOG_VERBOSITY"))
3298 COMPLETE_WITH("silent", "default", "verbose");
3299
3300 /* Complete COPY <sth> FROM <sth> WITH (<options>) */
3301 else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny, "WITH", MatchAny))
3302 COMPLETE_WITH("WHERE");
3303
3304 /* CREATE ACCESS METHOD */
3305 /* Complete "CREATE ACCESS METHOD <name>" */
3306 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny))
3307 COMPLETE_WITH("TYPE");
3308 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
3309 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
3310 COMPLETE_WITH("INDEX", "TABLE");
3311 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
3312 else if (Matches("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
3313 COMPLETE_WITH("HANDLER");
3314
3315 /* CREATE COLLATION */
3316 else if (Matches("CREATE", "COLLATION", MatchAny))
3317 COMPLETE_WITH("(", "FROM");
3318 else if (Matches("CREATE", "COLLATION", MatchAny, "FROM"))
3319 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_collations);
3320 else if (HeadMatches("CREATE", "COLLATION", MatchAny, "(*"))
3321 {
3322 if (TailMatches("(|*,"))
3323 COMPLETE_WITH("LOCALE =", "LC_COLLATE =", "LC_CTYPE =",
3324 "PROVIDER =", "DETERMINISTIC =");
3325 else if (TailMatches("PROVIDER", "="))
3326 COMPLETE_WITH("libc", "icu");
3327 else if (TailMatches("DETERMINISTIC", "="))
3328 COMPLETE_WITH("true", "false");
3329 }
3330
3331 /* CREATE DATABASE */
3332 else if (Matches("CREATE", "DATABASE", MatchAny))
3333 COMPLETE_WITH("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
3334 "IS_TEMPLATE", "STRATEGY",
3335 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
3336 "LC_COLLATE", "LC_CTYPE", "LOCALE", "OID",
3337 "LOCALE_PROVIDER", "ICU_LOCALE");
3338
3339 else if (Matches("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
3340 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
3341 else if (Matches("CREATE", "DATABASE", MatchAny, "STRATEGY"))
3342 COMPLETE_WITH("WAL_LOG", "FILE_COPY");
3343
3344 /* CREATE DOMAIN */
3345 else if (Matches("CREATE", "DOMAIN", MatchAny))
3346 COMPLETE_WITH("AS");
3347 else if (Matches("CREATE", "DOMAIN", MatchAny, "AS"))
3348 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
3349 else if (Matches("CREATE", "DOMAIN", MatchAny, "AS", MatchAny))
3350 COMPLETE_WITH("COLLATE", "DEFAULT", "CONSTRAINT",
3351 "NOT NULL", "NULL", "CHECK (");
3352 else if (Matches("CREATE", "DOMAIN", MatchAny, "COLLATE"))
3353 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_collations);
3354
3355 /* CREATE EXTENSION */
3356 /* Complete with available extensions rather than installed ones. */
3357 else if (Matches("CREATE", "EXTENSION"))
3358 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
3359 /* CREATE EXTENSION <name> */
3360 else if (Matches("CREATE", "EXTENSION", MatchAny))
3361 COMPLETE_WITH("WITH SCHEMA", "CASCADE", "VERSION");
3362 /* CREATE EXTENSION <name> VERSION */
3363 else if (Matches("CREATE", "EXTENSION", MatchAny, "VERSION"))
3364 {
3365 set_completion_reference(prev2_wd);
3366 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
3367 }
3368
3369 /* CREATE FOREIGN */
3370 else if (Matches("CREATE", "FOREIGN"))
3371 COMPLETE_WITH("DATA WRAPPER", "TABLE");
3372
3373 /* CREATE FOREIGN DATA WRAPPER */
3374 else if (Matches("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
3375 COMPLETE_WITH("HANDLER", "VALIDATOR", "OPTIONS");
3376
3377 /* CREATE FOREIGN TABLE */
3378 else if (Matches("CREATE", "FOREIGN", "TABLE", MatchAny))
3379 COMPLETE_WITH("(", "PARTITION OF");
3380
3381 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
3382 /* First off we complete CREATE UNIQUE with "INDEX" */
3383 else if (TailMatches("CREATE", "UNIQUE"))
3384 COMPLETE_WITH("INDEX");
3385
3386 /*
3387 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
3388 * existing indexes
3389 */
3390 else if (TailMatches("CREATE|UNIQUE", "INDEX"))
3391 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
3392 "ON", "CONCURRENTLY");
3393
3394 /*
3395 * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
3396 * that indexes can be created on
3397 */
3398 else if (TailMatches("INDEX|CONCURRENTLY", MatchAny, "ON") ||
3399 TailMatches("INDEX|CONCURRENTLY", "ON"))
3400 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexables);
3401
3402 /*
3403 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
3404 * indexes
3405 */
3406 else if (TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
3407 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
3408 "ON");
3409 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
3410 else if (TailMatches("CREATE|UNIQUE", "INDEX", MatchAny) ||
3411 TailMatches("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
3412 COMPLETE_WITH("ON");
3413
3414 /*
3415 * Complete INDEX <name> ON <table> with a list of table columns (which
3416 * should really be in parens)
3417 */
3418 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny) ||
3419 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny))
3420 COMPLETE_WITH("(", "USING");
3421 else if (TailMatches("INDEX", MatchAny, "ON", MatchAny, "(") ||
3422 TailMatches("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
3423 COMPLETE_WITH_ATTR(prev2_wd);
3424 /* same if you put in USING */
3425 else if (TailMatches("ON", MatchAny, "USING", MatchAny, "("))
3426 COMPLETE_WITH_ATTR(prev4_wd);
3427 /* Complete USING with an index method */
3428 else if (TailMatches("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
3429 TailMatches("INDEX", MatchAny, "ON", MatchAny, "USING") ||
3430 TailMatches("INDEX", "ON", MatchAny, "USING"))
3431 COMPLETE_WITH_QUERY(Query_for_list_of_index_access_methods);
3432 else if (TailMatches("ON", MatchAny, "USING", MatchAny) &&
3433 !TailMatches("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
3434 !TailMatches("FOR", MatchAny, MatchAny, MatchAny))
3435 COMPLETE_WITH("(");
3436
3437 /* CREATE OR REPLACE */
3438 else if (Matches("CREATE", "OR"))
3439 COMPLETE_WITH("REPLACE");
3440
3441 /* CREATE POLICY */
3442 /* Complete "CREATE POLICY <name> ON" */
3443 else if (Matches("CREATE", "POLICY", MatchAny))
3444 COMPLETE_WITH("ON");
3445 /* Complete "CREATE POLICY <name> ON <table>" */
3446 else if (Matches("CREATE", "POLICY", MatchAny, "ON"))
3447 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
3448 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
3449 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny))
3450 COMPLETE_WITH("AS", "FOR", "TO", "USING (", "WITH CHECK (");
3451 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
3452 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
3453 COMPLETE_WITH("PERMISSIVE", "RESTRICTIVE");
3454
3455 /*
3456 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3457 * FOR|TO|USING|WITH CHECK
3458 */
3459 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
3460 COMPLETE_WITH("FOR", "TO", "USING", "WITH CHECK");
3461 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
3462 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
3463 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3464 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
3465 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
3466 COMPLETE_WITH("TO", "WITH CHECK (");
3467 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
3468 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
3469 COMPLETE_WITH("TO", "USING (");
3470 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
3471 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
3472 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3473 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
3474 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
3475 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
3476 Keywords_for_list_of_grant_roles);
3477 /* Complete "CREATE POLICY <name> ON <table> USING (" */
3478 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
3479 COMPLETE_WITH("(");
3480
3481 /*
3482 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3483 * ALL|SELECT|INSERT|UPDATE|DELETE
3484 */
3485 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
3486 COMPLETE_WITH("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
3487
3488 /*
3489 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3490 * INSERT TO|WITH CHECK"
3491 */
3492 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
3493 COMPLETE_WITH("TO", "WITH CHECK (");
3494
3495 /*
3496 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3497 * SELECT|DELETE TO|USING"
3498 */
3499 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
3500 COMPLETE_WITH("TO", "USING (");
3501
3502 /*
3503 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
3504 * ALL|UPDATE TO|USING|WITH CHECK
3505 */
3506 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
3507 COMPLETE_WITH("TO", "USING (", "WITH CHECK (");
3508
3509 /*
3510 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
3511 * <role>"
3512 */
3513 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
3514 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
3515 Keywords_for_list_of_grant_roles);
3516
3517 /*
3518 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
3519 * USING ("
3520 */
3521 else if (Matches("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
3522 COMPLETE_WITH("(");
3523
3524
3525/* CREATE PUBLICATION */
3526 else if (Matches("CREATE", "PUBLICATION", MatchAny))
3527 COMPLETE_WITH("FOR TABLE", "FOR ALL TABLES", "FOR TABLES IN SCHEMA", "WITH (");
3528 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR"))
3529 COMPLETE_WITH("TABLE", "ALL TABLES", "TABLES IN SCHEMA");
3530 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL"))
3531 COMPLETE_WITH("TABLES");
3532 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "ALL", "TABLES"))
3533 COMPLETE_WITH("WITH (");
3534 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES"))
3535 COMPLETE_WITH("IN SCHEMA");
3536 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE", MatchAny) && !ends_with(prev_wd, ','))
3537 COMPLETE_WITH("WHERE (", "WITH (");
3538 /* Complete "CREATE PUBLICATION <name> FOR TABLE" with "<table>, ..." */
3539 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLE"))
3540 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
3541
3542 /*
3543 * "CREATE PUBLICATION <name> FOR TABLE <name> WHERE (" - complete with
3544 * table attributes
3545 */
3546 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE"))
3547 COMPLETE_WITH("(");
3548 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "("))
3549 COMPLETE_WITH_ATTR(prev3_wd);
3550 else if (Matches("CREATE", "PUBLICATION", MatchAny, MatchAnyN, "WHERE", "(*)"))
3551 COMPLETE_WITH(" WITH (");
3552
3553 /*
3554 * Complete "CREATE PUBLICATION <name> FOR TABLES IN SCHEMA <schema>, ..."
3555 */
3556 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA"))
3557 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
3558 " AND nspname NOT LIKE E'pg\\\\_%%'",
3559 "CURRENT_SCHEMA");
3560 else if (Matches("CREATE", "PUBLICATION", MatchAny, "FOR", "TABLES", "IN", "SCHEMA", MatchAny) && (!ends_with(prev_wd, ',')))
3561 COMPLETE_WITH("WITH (");
3562 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
3563 else if (Matches("CREATE", "PUBLICATION", MatchAnyN, "WITH", "("))
3564 COMPLETE_WITH("publish", "publish_generated_columns", "publish_via_partition_root");
3565
3566/* CREATE RULE */
3567 /* Complete "CREATE [ OR REPLACE ] RULE <sth>" with "AS ON" */
3568 else if (Matches("CREATE", "RULE", MatchAny) ||
3569 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny))
3570 COMPLETE_WITH("AS ON");
3571 /* Complete "CREATE [ OR REPLACE ] RULE <sth> AS" with "ON" */
3572 else if (Matches("CREATE", "RULE", MatchAny, "AS") ||
3573 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS"))
3574 COMPLETE_WITH("ON");
3575
3576 /*
3577 * Complete "CREATE [ OR REPLACE ] RULE <sth> AS ON" with
3578 * SELECT|UPDATE|INSERT|DELETE
3579 */
3580 else if (Matches("CREATE", "RULE", MatchAny, "AS", "ON") ||
3581 Matches("CREATE", "OR", "REPLACE", "RULE", MatchAny, "AS", "ON"))
3582 COMPLETE_WITH("SELECT", "UPDATE", "INSERT", "DELETE");
3583 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
3584 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
3585 COMPLETE_WITH("TO");
3586 /* Complete "AS ON <sth> TO" with a table name */
3587 else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
3588 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
3589
3590/* CREATE SCHEMA [ <name> ] [ AUTHORIZATION ] */
3591 else if (Matches("CREATE", "SCHEMA"))
3592 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas,
3593 "AUTHORIZATION");
3594 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION") ||
3595 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION"))
3596 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
3597 Keywords_for_list_of_owner_roles);
3598 else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION", MatchAny) ||
3599 Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION", MatchAny))
3600 COMPLETE_WITH("CREATE", "GRANT");
3601 else if (Matches("CREATE", "SCHEMA", MatchAny))
3602 COMPLETE_WITH("AUTHORIZATION", "CREATE", "GRANT");
3603
3604/* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3605 else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
3606 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
3607 COMPLETE_WITH("AS", "INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
3608 "CACHE", "CYCLE", "OWNED BY", "START WITH");
3609 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "AS") ||
3610 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "AS"))
3611 COMPLETE_WITH_CS("smallint", "integer", "bigint");
3612 else if (TailMatches("CREATE", "SEQUENCE", MatchAny, "NO") ||
3613 TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
3614 COMPLETE_WITH("MINVALUE", "MAXVALUE", "CYCLE");
3615
3616/* CREATE SERVER <name> */
3617 else if (Matches("CREATE", "SERVER", MatchAny))
3618 COMPLETE_WITH("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
3619
3620/* CREATE STATISTICS <name> */
3621 else if (Matches("CREATE", "STATISTICS", MatchAny))
3622 COMPLETE_WITH("(", "ON");
3623 else if (Matches("CREATE", "STATISTICS", MatchAny, "("))
3624 COMPLETE_WITH("ndistinct", "dependencies", "mcv");
3625 else if (Matches("CREATE", "STATISTICS", MatchAny, "(*)"))
3626 COMPLETE_WITH("ON");
3627 else if (Matches("CREATE", "STATISTICS", MatchAny, MatchAnyN, "FROM"))
3628 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
3629
3630/* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
3631 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
3632 else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
3633 COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW");
3634 /* Complete "CREATE UNLOGGED" with TABLE or SEQUENCE */
3635 else if (TailMatches("CREATE", "UNLOGGED"))
3636 COMPLETE_WITH("TABLE", "SEQUENCE");
3637 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
3638 else if (TailMatches("PARTITION", "BY"))
3639 COMPLETE_WITH("RANGE (", "LIST (", "HASH (");
3640 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
3641 else if (TailMatches("PARTITION", "OF"))
3642 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables);
3643 /* Limited completion support for partition bound specification */
3644 else if (TailMatches("PARTITION", "OF", MatchAny))
3645 COMPLETE_WITH("FOR VALUES", "DEFAULT");
3646 /* Complete CREATE TABLE <name> with '(', AS, OF or PARTITION OF */
3647 else if (TailMatches("CREATE", "TABLE", MatchAny) ||
3648 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny))
3649 COMPLETE_WITH("(", "AS", "OF", "PARTITION OF");
3650 /* Complete CREATE TABLE <name> OF with list of composite types */
3651 else if (TailMatches("CREATE", "TABLE", MatchAny, "OF") ||
3652 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "OF"))
3653 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_composite_datatypes);
3654 /* Complete CREATE TABLE <name> [ (...) ] AS with list of keywords */
3655 else if (TailMatches("CREATE", "TABLE", MatchAny, "AS") ||
3656 TailMatches("CREATE", "TABLE", MatchAny, "(*)", "AS") ||
3657 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "AS") ||
3658 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "AS"))
3659 COMPLETE_WITH("EXECUTE", "SELECT", "TABLE", "VALUES", "WITH");
3660 /* Complete CREATE TABLE name (...) with supported options */
3661 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)") ||
3662 TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)"))
3663 COMPLETE_WITH("AS", "INHERITS (", "PARTITION BY", "USING", "TABLESPACE", "WITH (");
3664 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)"))
3665 COMPLETE_WITH("AS", "INHERITS (", "ON COMMIT", "PARTITION BY", "USING",
3666 "TABLESPACE", "WITH (");
3667 /* Complete CREATE TABLE (...) USING with table access methods */
3668 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "USING") ||
3669 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "USING"))
3670 COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
3671 /* Complete CREATE TABLE (...) WITH with storage parameters */
3672 else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)", "WITH", "(") ||
3673 TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "(*)", "WITH", "("))
3674 COMPLETE_WITH_LIST(table_storage_parameters);
3675 /* Complete CREATE TABLE ON COMMIT with actions */
3676 else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)", "ON", "COMMIT"))
3677 COMPLETE_WITH("DELETE ROWS", "DROP", "PRESERVE ROWS");
3678
3679/* CREATE TABLESPACE */
3680 else if (Matches("CREATE", "TABLESPACE", MatchAny))
3681 COMPLETE_WITH("OWNER", "LOCATION");
3682 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
3683 else if (Matches("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
3684 COMPLETE_WITH("LOCATION");
3685
3686/* CREATE TEXT SEARCH */
3687 else if (Matches("CREATE", "TEXT", "SEARCH"))
3688 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3689 else if (Matches("CREATE", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
3690 COMPLETE_WITH("(");
3691
3692/* CREATE TRANSFORM */
3693 else if (Matches("CREATE", "TRANSFORM") ||
3694 Matches("CREATE", "OR", "REPLACE", "TRANSFORM"))
3695 COMPLETE_WITH("FOR");
3696 else if (Matches("CREATE", "TRANSFORM", "FOR") ||
3697 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR"))
3698 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
3699 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny) ||
3700 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny))
3701 COMPLETE_WITH("LANGUAGE");
3702 else if (Matches("CREATE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE") ||
3703 Matches("CREATE", "OR", "REPLACE", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
3704 {
3705 set_completion_reference(prev2_wd);
3706 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3707 }
3708
3709/* CREATE SUBSCRIPTION */
3710 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny))
3711 COMPLETE_WITH("CONNECTION");
3712 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
3713 COMPLETE_WITH("PUBLICATION");
3714 else if (Matches("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
3715 MatchAny, "PUBLICATION"))
3716 {
3717 /* complete with nothing here as this refers to remote publications */
3718 }
3719 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "PUBLICATION", MatchAny))
3720 COMPLETE_WITH("WITH (");
3721 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
3722 else if (Matches("CREATE", "SUBSCRIPTION", MatchAnyN, "WITH", "("))
3723 COMPLETE_WITH("binary", "connect", "copy_data", "create_slot",
3724 "disable_on_error", "enabled", "failover", "origin",
3725 "password_required", "run_as_owner", "slot_name",
3726 "streaming", "synchronous_commit", "two_phase");
3727
3728/* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
3729
3730 /*
3731 * Complete CREATE [ OR REPLACE ] TRIGGER <name> with BEFORE|AFTER|INSTEAD
3732 * OF.
3733 */
3734 else if (TailMatches("CREATE", "TRIGGER", MatchAny) ||
3735 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny))
3736 COMPLETE_WITH("BEFORE", "AFTER", "INSTEAD OF");
3737
3738 /*
3739 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER with an
3740 * event.
3741 */
3742 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER") ||
3743 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
3744 COMPLETE_WITH("INSERT", "DELETE", "UPDATE", "TRUNCATE");
3745 /* Complete CREATE [ OR REPLACE ] TRIGGER <name> INSTEAD OF with an event */
3746 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF") ||
3747 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
3748 COMPLETE_WITH("INSERT", "DELETE", "UPDATE");
3749
3750 /*
3751 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER sth with
3752 * OR|ON.
3753 */
3754 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3755 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
3756 TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny) ||
3757 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
3758 COMPLETE_WITH("ON", "OR");
3759
3760 /*
3761 * Complete CREATE [ OR REPLACE ] TRIGGER <name> BEFORE,AFTER event ON
3762 * with a list of tables. EXECUTE FUNCTION is the recommended grammar
3763 * instead of EXECUTE PROCEDURE in version 11 and upwards.
3764 */
3765 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON") ||
3766 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
3767 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
3768
3769 /*
3770 * Complete CREATE [ OR REPLACE ] TRIGGER ... INSTEAD OF event ON with a
3771 * list of views.
3772 */
3773 else if (TailMatches("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON") ||
3774 TailMatches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
3775 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
3776 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3777 "ON", MatchAny) ||
3778 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3779 "ON", MatchAny))
3780 {
3781 if (pset.sversion >= 110000)
3782 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
3783 "REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
3784 else
3785 COMPLETE_WITH("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
3786 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
3787 }
3788 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3789 "DEFERRABLE") ||
3790 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3791 "DEFERRABLE") ||
3792 Matches("CREATE", "TRIGGER", MatchAnyN,
3793 "INITIALLY", "IMMEDIATE|DEFERRED") ||
3794 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3795 "INITIALLY", "IMMEDIATE|DEFERRED"))
3796 {
3797 if (pset.sversion >= 110000)
3798 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE FUNCTION");
3799 else
3800 COMPLETE_WITH("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
3801 }
3802 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3803 "REFERENCING") ||
3804 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3805 "REFERENCING"))
3806 COMPLETE_WITH("OLD TABLE", "NEW TABLE");
3807 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3808 "OLD|NEW", "TABLE") ||
3809 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3810 "OLD|NEW", "TABLE"))
3811 COMPLETE_WITH("AS");
3812 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3813 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
3814 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3815 "REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
3816 Matches("CREATE", "TRIGGER", MatchAnyN,
3817 "REFERENCING", "OLD", "TABLE", MatchAny) ||
3818 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3819 "REFERENCING", "OLD", "TABLE", MatchAny))
3820 {
3821 if (pset.sversion >= 110000)
3822 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
3823 else
3824 COMPLETE_WITH("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
3825 }
3826 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3827 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
3828 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3829 "REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
3830 Matches("CREATE", "TRIGGER", MatchAnyN,
3831 "REFERENCING", "NEW", "TABLE", MatchAny) ||
3832 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3833 "REFERENCING", "NEW", "TABLE", MatchAny))
3834 {
3835 if (pset.sversion >= 110000)
3836 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE FUNCTION");
3837 else
3838 COMPLETE_WITH("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
3839 }
3840 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3841 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
3842 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3843 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
3844 Matches("CREATE", "TRIGGER", MatchAnyN,
3845 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
3846 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3847 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
3848 Matches("CREATE", "TRIGGER", MatchAnyN,
3849 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
3850 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3851 "REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
3852 Matches("CREATE", "TRIGGER", MatchAnyN,
3853 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
3854 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3855 "REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny))
3856 {
3857 if (pset.sversion >= 110000)
3858 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE FUNCTION");
3859 else
3860 COMPLETE_WITH("FOR", "WHEN (", "EXECUTE PROCEDURE");
3861 }
3862 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3863 "FOR") ||
3864 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3865 "FOR"))
3866 COMPLETE_WITH("EACH", "ROW", "STATEMENT");
3867 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3868 "FOR", "EACH") ||
3869 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3870 "FOR", "EACH"))
3871 COMPLETE_WITH("ROW", "STATEMENT");
3872 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3873 "FOR", "EACH", "ROW|STATEMENT") ||
3874 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3875 "FOR", "EACH", "ROW|STATEMENT") ||
3876 Matches("CREATE", "TRIGGER", MatchAnyN,
3877 "FOR", "ROW|STATEMENT") ||
3878 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3879 "FOR", "ROW|STATEMENT"))
3880 {
3881 if (pset.sversion >= 110000)
3882 COMPLETE_WITH("WHEN (", "EXECUTE FUNCTION");
3883 else
3884 COMPLETE_WITH("WHEN (", "EXECUTE PROCEDURE");
3885 }
3886 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3887 "WHEN", "(*)") ||
3888 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3889 "WHEN", "(*)"))
3890 {
3891 if (pset.sversion >= 110000)
3892 COMPLETE_WITH("EXECUTE FUNCTION");
3893 else
3894 COMPLETE_WITH("EXECUTE PROCEDURE");
3895 }
3896
3897 /*
3898 * Complete CREATE [ OR REPLACE ] TRIGGER ... EXECUTE with
3899 * PROCEDURE|FUNCTION.
3900 */
3901 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3902 "EXECUTE") ||
3903 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3904 "EXECUTE"))
3905 {
3906 if (pset.sversion >= 110000)
3907 COMPLETE_WITH("FUNCTION");
3908 else
3909 COMPLETE_WITH("PROCEDURE");
3910 }
3911 else if (Matches("CREATE", "TRIGGER", MatchAnyN,
3912 "EXECUTE", "FUNCTION|PROCEDURE") ||
3913 Matches("CREATE", "OR", "REPLACE", "TRIGGER", MatchAnyN,
3914 "EXECUTE", "FUNCTION|PROCEDURE"))
3915 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
3916
3917/* CREATE ROLE,USER,GROUP <name> */
3918 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny) &&
3919 !TailMatches("USER", "MAPPING"))
3920 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
3921 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
3922 "LOGIN", "NOBYPASSRLS",
3923 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
3924 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
3925 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
3926 "VALID UNTIL", "WITH");
3927
3928/* CREATE ROLE,USER,GROUP <name> WITH */
3929 else if (Matches("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
3930 /* Similar to the above, but don't complete "WITH" again. */
3931 COMPLETE_WITH("ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB",
3932 "CREATEROLE", "ENCRYPTED PASSWORD", "IN", "INHERIT",
3933 "LOGIN", "NOBYPASSRLS",
3934 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
3935 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
3936 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
3937 "VALID UNTIL");
3938
3939 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
3940 else if (Matches("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
3941 COMPLETE_WITH("GROUP", "ROLE");
3942
3943/* CREATE TYPE */
3944 else if (Matches("CREATE", "TYPE", MatchAny))
3945 COMPLETE_WITH("(", "AS");
3946 else if (Matches("CREATE", "TYPE", MatchAny, "AS"))
3947 COMPLETE_WITH("ENUM", "RANGE", "(");
3948 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "("))
3949 {
3950 if (TailMatches("(|*,", MatchAny))
3951 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
3952 else if (TailMatches("(|*,", MatchAny, MatchAnyExcept("*)")))
3953 COMPLETE_WITH("COLLATE", ",", ")");
3954 }
3955 else if (Matches("CREATE", "TYPE", MatchAny, "AS", "ENUM|RANGE"))
3956 COMPLETE_WITH("(");
3957 else if (HeadMatches("CREATE", "TYPE", MatchAny, "("))
3958 {
3959 if (TailMatches("(|*,"))
3960 COMPLETE_WITH("INPUT", "OUTPUT", "RECEIVE", "SEND",
3961 "TYPMOD_IN", "TYPMOD_OUT", "ANALYZE", "SUBSCRIPT",
3962 "INTERNALLENGTH", "PASSEDBYVALUE", "ALIGNMENT",
3963 "STORAGE", "LIKE", "CATEGORY", "PREFERRED",
3964 "DEFAULT", "ELEMENT", "DELIMITER",
3965 "COLLATABLE");
3966 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
3967 COMPLETE_WITH("=");
3968 else if (TailMatches("=", MatchAnyExcept("*)")))
3969 COMPLETE_WITH(",", ")");
3970 }
3971 else if (HeadMatches("CREATE", "TYPE", MatchAny, "AS", "RANGE", "("))
3972 {
3973 if (TailMatches("(|*,"))
3974 COMPLETE_WITH("SUBTYPE", "SUBTYPE_OPCLASS", "COLLATION",
3975 "CANONICAL", "SUBTYPE_DIFF",
3976 "MULTIRANGE_TYPE_NAME");
3977 else if (TailMatches("(*|*,", MatchAnyExcept("*=")))
3978 COMPLETE_WITH("=");
3979 else if (TailMatches("=", MatchAnyExcept("*)")))
3980 COMPLETE_WITH(",", ")");
3981 }
3982
3983/* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
3984 /* Complete CREATE [ OR REPLACE ] VIEW <name> with AS or WITH */
3985 else if (TailMatches("CREATE", "VIEW", MatchAny) ||
3986 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny))
3987 COMPLETE_WITH("AS", "WITH");
3988 /* Complete "CREATE [ OR REPLACE ] VIEW <sth> AS with "SELECT" */
3989 else if (TailMatches("CREATE", "VIEW", MatchAny, "AS") ||
3990 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "AS"))
3991 COMPLETE_WITH("SELECT");
3992 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( yyy [= zzz] ) */
3993 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH") ||
3994 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH"))
3995 COMPLETE_WITH("(");
3996 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(") ||
3997 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "("))
3998 COMPLETE_WITH_LIST(view_optional_parameters);
3999 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option") ||
4000 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option"))
4001 COMPLETE_WITH("=");
4002 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(", "check_option", "=") ||
4003 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(", "check_option", "="))
4004 COMPLETE_WITH("local", "cascaded");
4005 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS */
4006 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)") ||
4007 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)"))
4008 COMPLETE_WITH("AS");
4009 /* CREATE [ OR REPLACE ] VIEW <name> WITH ( ... ) AS SELECT */
4010 else if (TailMatches("CREATE", "VIEW", MatchAny, "WITH", "(*)", "AS") ||
4011 TailMatches("CREATE", "OR", "REPLACE", "VIEW", MatchAny, "WITH", "(*)", "AS"))
4012 COMPLETE_WITH("SELECT");
4013
4014/* CREATE MATERIALIZED VIEW */
4015 else if (Matches("CREATE", "MATERIALIZED"))
4016 COMPLETE_WITH("VIEW");
4017 /* Complete CREATE MATERIALIZED VIEW <name> with AS or USING */
4018 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny))
4019 COMPLETE_WITH("AS", "USING");
4020
4021 /*
4022 * Complete CREATE MATERIALIZED VIEW <name> USING with list of access
4023 * methods
4024 */
4025 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING"))
4026 COMPLETE_WITH_QUERY(Query_for_list_of_table_access_methods);
4027 /* Complete CREATE MATERIALIZED VIEW <name> USING <access method> with AS */
4028 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny))
4029 COMPLETE_WITH("AS");
4030
4031 /*
4032 * Complete CREATE MATERIALIZED VIEW <name> [USING <access method> ] AS
4033 * with "SELECT"
4034 */
4035 else if (Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS") ||
4036 Matches("CREATE", "MATERIALIZED", "VIEW", MatchAny, "USING", MatchAny, "AS"))
4037 COMPLETE_WITH("SELECT");
4038
4039/* CREATE EVENT TRIGGER */
4040 else if (Matches("CREATE", "EVENT"))
4041 COMPLETE_WITH("TRIGGER");
4042 /* Complete CREATE EVENT TRIGGER <name> with ON */
4043 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny))
4044 COMPLETE_WITH("ON");
4045 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
4046 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
4047 COMPLETE_WITH("ddl_command_start", "ddl_command_end", "login",
4048 "sql_drop", "table_rewrite");
4049
4050 /*
4051 * Complete CREATE EVENT TRIGGER <name> ON <event_type>. EXECUTE FUNCTION
4052 * is the recommended grammar instead of EXECUTE PROCEDURE in version 11
4053 * and upwards.
4054 */
4055 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAny, "ON", MatchAny))
4056 {
4057 if (pset.sversion >= 110000)
4058 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE FUNCTION");
4059 else
4060 COMPLETE_WITH("WHEN TAG IN (", "EXECUTE PROCEDURE");
4061 }
4062 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "WHEN|AND", MatchAny, "IN", "(*)"))
4063 {
4064 if (pset.sversion >= 110000)
4065 COMPLETE_WITH("EXECUTE FUNCTION");
4066 else
4067 COMPLETE_WITH("EXECUTE PROCEDURE");
4068 }
4069 else if (Matches("CREATE", "EVENT", "TRIGGER", MatchAnyN, "EXECUTE", "FUNCTION|PROCEDURE"))
4070 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
4071
4072/* DEALLOCATE */
4073 else if (Matches("DEALLOCATE"))
4074 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_prepared_statements,
4075 "ALL");
4076
4077/* DECLARE */
4078
4079 /*
4080 * Complete DECLARE <name> with one of BINARY, ASENSITIVE, INSENSITIVE,
4081 * SCROLL, NO SCROLL, and CURSOR.
4082 */
4083 else if (Matches("DECLARE", MatchAny))
4084 COMPLETE_WITH("BINARY", "ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL",
4085 "CURSOR");
4086
4087 /*
4088 * Complete DECLARE ... <option> with other options. The PostgreSQL parser
4089 * allows DECLARE options to be specified in any order. But the
4090 * tab-completion follows the ordering of them that the SQL standard
4091 * provides, like the syntax of DECLARE command in the documentation
4092 * indicates.
4093 */
4094 else if (Matches("DECLARE", MatchAnyN, "BINARY"))
4095 COMPLETE_WITH("ASENSITIVE", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR");
4096 else if (Matches("DECLARE", MatchAnyN, "ASENSITIVE|INSENSITIVE"))
4097 COMPLETE_WITH("SCROLL", "NO SCROLL", "CURSOR");
4098 else if (Matches("DECLARE", MatchAnyN, "SCROLL"))
4099 COMPLETE_WITH("CURSOR");
4100 /* Complete DECLARE ... [options] NO with SCROLL */
4101 else if (Matches("DECLARE", MatchAnyN, "NO"))
4102 COMPLETE_WITH("SCROLL");
4103
4104 /*
4105 * Complete DECLARE ... CURSOR with one of WITH HOLD, WITHOUT HOLD, and
4106 * FOR
4107 */
4108 else if (Matches("DECLARE", MatchAnyN, "CURSOR"))
4109 COMPLETE_WITH("WITH HOLD", "WITHOUT HOLD", "FOR");
4110 /* Complete DECLARE ... CURSOR WITH|WITHOUT with HOLD */
4111 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT"))
4112 COMPLETE_WITH("HOLD");
4113 /* Complete DECLARE ... CURSOR WITH|WITHOUT HOLD with FOR */
4114 else if (Matches("DECLARE", MatchAnyN, "CURSOR", "WITH|WITHOUT", "HOLD"))
4115 COMPLETE_WITH("FOR");
4116
4117/* DELETE --- can be inside EXPLAIN, RULE, etc */
4118 /* Complete DELETE with "FROM" */
4119 else if (Matches("DELETE"))
4120 COMPLETE_WITH("FROM");
4121 /* Complete DELETE FROM with a list of tables */
4122 else if (TailMatches("DELETE", "FROM"))
4123 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
4124 /* Complete DELETE FROM <table> */
4125 else if (TailMatches("DELETE", "FROM", MatchAny))
4126 COMPLETE_WITH("USING", "WHERE");
4127 /* XXX: implement tab completion for DELETE ... USING */
4128
4129/* DISCARD */
4130 else if (Matches("DISCARD"))
4131 COMPLETE_WITH("ALL", "PLANS", "SEQUENCES", "TEMP");
4132
4133/* DO */
4134 else if (Matches("DO"))
4135 COMPLETE_WITH("LANGUAGE");
4136
4137/* DROP */
4138 /* Complete DROP object with CASCADE / RESTRICT */
4139 else if (Matches("DROP",
4140 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
4141 MatchAny) ||
4142 Matches("DROP", "ACCESS", "METHOD", MatchAny) ||
4143 Matches("DROP", "EVENT", "TRIGGER", MatchAny) ||
4144 Matches("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4145 Matches("DROP", "FOREIGN", "TABLE", MatchAny) ||
4146 Matches("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
4147 COMPLETE_WITH("CASCADE", "RESTRICT");
4148 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
4149 ends_with(prev_wd, ')'))
4150 COMPLETE_WITH("CASCADE", "RESTRICT");
4151
4152 /* help completing some of the variants */
4153 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
4154 COMPLETE_WITH("(");
4155 else if (Matches("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
4156 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
4157 else if (Matches("DROP", "FOREIGN"))
4158 COMPLETE_WITH("DATA WRAPPER", "TABLE");
4159 else if (Matches("DROP", "DATABASE", MatchAny))
4160 COMPLETE_WITH("WITH (");
4161 else if (HeadMatches("DROP", "DATABASE") && (ends_with(prev_wd, '(')))
4162 COMPLETE_WITH("FORCE");
4163
4164 /* DROP INDEX */
4165 else if (Matches("DROP", "INDEX"))
4166 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
4167 "CONCURRENTLY");
4168 else if (Matches("DROP", "INDEX", "CONCURRENTLY"))
4169 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
4170 else if (Matches("DROP", "INDEX", MatchAny))
4171 COMPLETE_WITH("CASCADE", "RESTRICT");
4172 else if (Matches("DROP", "INDEX", "CONCURRENTLY", MatchAny))
4173 COMPLETE_WITH("CASCADE", "RESTRICT");
4174
4175 /* DROP MATERIALIZED VIEW */
4176 else if (Matches("DROP", "MATERIALIZED"))
4177 COMPLETE_WITH("VIEW");
4178 else if (Matches("DROP", "MATERIALIZED", "VIEW"))
4179 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
4180 else if (Matches("DROP", "MATERIALIZED", "VIEW", MatchAny))
4181 COMPLETE_WITH("CASCADE", "RESTRICT");
4182
4183 /* DROP OWNED BY */
4184 else if (Matches("DROP", "OWNED"))
4185 COMPLETE_WITH("BY");
4186 else if (Matches("DROP", "OWNED", "BY"))
4187 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
4188 else if (Matches("DROP", "OWNED", "BY", MatchAny))
4189 COMPLETE_WITH("CASCADE", "RESTRICT");
4190
4191 /* DROP TEXT SEARCH */
4192 else if (Matches("DROP", "TEXT", "SEARCH"))
4193 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
4194
4195 /* DROP TRIGGER */
4196 else if (Matches("DROP", "TRIGGER", MatchAny))
4197 COMPLETE_WITH("ON");
4198 else if (Matches("DROP", "TRIGGER", MatchAny, "ON"))
4199 {
4200 set_completion_reference(prev2_wd);
4201 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_trigger);
4202 }
4203 else if (Matches("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
4204 COMPLETE_WITH("CASCADE", "RESTRICT");
4205
4206 /* DROP ACCESS METHOD */
4207 else if (Matches("DROP", "ACCESS"))
4208 COMPLETE_WITH("METHOD");
4209 else if (Matches("DROP", "ACCESS", "METHOD"))
4210 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
4211
4212 /* DROP EVENT TRIGGER */
4213 else if (Matches("DROP", "EVENT"))
4214 COMPLETE_WITH("TRIGGER");
4215 else if (Matches("DROP", "EVENT", "TRIGGER"))
4216 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
4217
4218 /* DROP POLICY <name> */
4219 else if (Matches("DROP", "POLICY"))
4220 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
4221 /* DROP POLICY <name> ON */
4222 else if (Matches("DROP", "POLICY", MatchAny))
4223 COMPLETE_WITH("ON");
4224 /* DROP POLICY <name> ON <table> */
4225 else if (Matches("DROP", "POLICY", MatchAny, "ON"))
4226 {
4227 set_completion_reference(prev2_wd);
4228 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_policy);
4229 }
4230 else if (Matches("DROP", "POLICY", MatchAny, "ON", MatchAny))
4231 COMPLETE_WITH("CASCADE", "RESTRICT");
4232
4233 /* DROP RULE */
4234 else if (Matches("DROP", "RULE", MatchAny))
4235 COMPLETE_WITH("ON");
4236 else if (Matches("DROP", "RULE", MatchAny, "ON"))
4237 {
4238 set_completion_reference(prev2_wd);
4239 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables_for_rule);
4240 }
4241 else if (Matches("DROP", "RULE", MatchAny, "ON", MatchAny))
4242 COMPLETE_WITH("CASCADE", "RESTRICT");
4243
4244 /* DROP TRANSFORM */
4245 else if (Matches("DROP", "TRANSFORM"))
4246 COMPLETE_WITH("FOR");
4247 else if (Matches("DROP", "TRANSFORM", "FOR"))
4248 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
4249 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny))
4250 COMPLETE_WITH("LANGUAGE");
4251 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE"))
4252 {
4253 set_completion_reference(prev2_wd);
4254 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
4255 }
4256 else if (Matches("DROP", "TRANSFORM", "FOR", MatchAny, "LANGUAGE", MatchAny))
4257 COMPLETE_WITH("CASCADE", "RESTRICT");
4258
4259/* EXECUTE */
4260 else if (Matches("EXECUTE"))
4261 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
4262
4263/*
4264 * EXPLAIN [ ( option [, ...] ) ] statement
4265 * EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
4266 */
4267 else if (Matches("EXPLAIN"))
4268 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4269 "MERGE INTO", "EXECUTE", "ANALYZE", "VERBOSE");
4270 else if (HeadMatches("EXPLAIN", "(*") &&
4271 !HeadMatches("EXPLAIN", "(*)"))
4272 {
4273 /*
4274 * This fires if we're in an unfinished parenthesized option list.
4275 * get_previous_words treats a completed parenthesized option list as
4276 * one word, so the above test is correct.
4277 */
4278 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
4279 COMPLETE_WITH("ANALYZE", "VERBOSE", "COSTS", "SETTINGS", "GENERIC_PLAN",
4280 "BUFFERS", "SERIALIZE", "WAL", "TIMING", "SUMMARY",
4281 "MEMORY", "FORMAT");
4282 else if (TailMatches("ANALYZE|VERBOSE|COSTS|SETTINGS|GENERIC_PLAN|BUFFERS|WAL|TIMING|SUMMARY|MEMORY"))
4283 COMPLETE_WITH("ON", "OFF");
4284 else if (TailMatches("SERIALIZE"))
4285 COMPLETE_WITH("TEXT", "NONE", "BINARY");
4286 else if (TailMatches("FORMAT"))
4287 COMPLETE_WITH("TEXT", "XML", "JSON", "YAML");
4288 }
4289 else if (Matches("EXPLAIN", "ANALYZE"))
4290 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4291 "MERGE INTO", "EXECUTE", "VERBOSE");
4292 else if (Matches("EXPLAIN", "(*)") ||
4293 Matches("EXPLAIN", "VERBOSE") ||
4294 Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
4295 COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", "DECLARE",
4296 "MERGE INTO", "EXECUTE");
4297
4298/* FETCH && MOVE */
4299
4300 /*
4301 * Complete FETCH with one of ABSOLUTE, BACKWARD, FORWARD, RELATIVE, ALL,
4302 * NEXT, PRIOR, FIRST, LAST, FROM, IN, and a list of cursors
4303 */
4304 else if (Matches("FETCH|MOVE"))
4305 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
4306 "ABSOLUTE",
4307 "BACKWARD",
4308 "FORWARD",
4309 "RELATIVE",
4310 "ALL",
4311 "NEXT",
4312 "PRIOR",
4313 "FIRST",
4314 "LAST",
4315 "FROM",
4316 "IN");
4317
4318 /*
4319 * Complete FETCH BACKWARD or FORWARD with one of ALL, FROM, IN, and a
4320 * list of cursors
4321 */
4322 else if (Matches("FETCH|MOVE", "BACKWARD|FORWARD"))
4323 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
4324 "ALL",
4325 "FROM",
4326 "IN");
4327
4328 /*
4329 * Complete FETCH <direction> with "FROM" or "IN". These are equivalent,
4330 * but we may as well tab-complete both: perhaps some users prefer one
4331 * variant or the other.
4332 */
4333 else if (Matches("FETCH|MOVE", "ABSOLUTE|BACKWARD|FORWARD|RELATIVE",
4334 MatchAnyExcept("FROM|IN")) ||
4335 Matches("FETCH|MOVE", "ALL|NEXT|PRIOR|FIRST|LAST"))
4336 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_cursors,
4337 "FROM",
4338 "IN");
4339 /* Complete FETCH <direction> "FROM" or "IN" with a list of cursors */
4340 else if (Matches("FETCH|MOVE", MatchAnyN, "FROM|IN"))
4341 COMPLETE_WITH_QUERY(Query_for_list_of_cursors);
4342
4343/* FOREIGN DATA WRAPPER */
4344 /* applies in ALTER/DROP FDW and in CREATE SERVER */
4345 else if (TailMatches("FOREIGN", "DATA", "WRAPPER") &&
4346 !TailMatches("CREATE", MatchAny, MatchAny, MatchAny))
4347 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
4348 /* applies in CREATE SERVER */
4349 else if (Matches("CREATE", "SERVER", MatchAnyN, "FOREIGN", "DATA", "WRAPPER", MatchAny))
4350 COMPLETE_WITH("OPTIONS");
4351
4352/* FOREIGN TABLE */
4353 else if (TailMatches("FOREIGN", "TABLE") &&
4354 !TailMatches("CREATE", MatchAny, MatchAny))
4355 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
4356
4357/* FOREIGN SERVER */
4358 else if (TailMatches("FOREIGN", "SERVER"))
4359 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
4360
4361/*
4362 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
4363 * ALTER DEFAULT PRIVILEGES, so use TailMatches
4364 */
4365 /* Complete GRANT/REVOKE with a list of roles and privileges */
4366 else if (TailMatches("GRANT|REVOKE") ||
4367 TailMatches("REVOKE", "ADMIN|GRANT|INHERIT|SET", "OPTION", "FOR"))
4368 {
4369 /*
4370 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
4371 * privileges (can't grant roles)
4372 */
4373 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4374 {
4375 if (TailMatches("GRANT") ||
4376 TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4377 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4378 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4379 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL");
4380 else if (TailMatches("REVOKE"))
4381 COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
4382 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
4383 "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL",
4384 "GRANT OPTION FOR");
4385 }
4386 else if (TailMatches("GRANT"))
4387 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4388 Privilege_options_of_grant_and_revoke);
4389 else if (TailMatches("REVOKE"))
4390 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4391 Privilege_options_of_grant_and_revoke,
4392 "GRANT OPTION FOR",
4393 "ADMIN OPTION FOR",
4394 "INHERIT OPTION FOR",
4395 "SET OPTION FOR");
4396 else if (TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
4397 COMPLETE_WITH(Privilege_options_of_grant_and_revoke);
4398 else if (TailMatches("REVOKE", "ADMIN|INHERIT|SET", "OPTION", "FOR"))
4399 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
4400 }
4401
4402 else if (TailMatches("GRANT|REVOKE", "ALTER") ||
4403 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER"))
4404 COMPLETE_WITH("SYSTEM");
4405
4406 else if (TailMatches("REVOKE", "SET"))
4407 COMPLETE_WITH("ON PARAMETER", "OPTION FOR");
4408 else if (TailMatches("GRANT", "SET") ||
4409 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "SET") ||
4410 TailMatches("GRANT|REVOKE", "ALTER", "SYSTEM") ||
4411 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALTER", "SYSTEM"))
4412 COMPLETE_WITH("ON PARAMETER");
4413
4414 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "PARAMETER") ||
4415 TailMatches("GRANT|REVOKE", MatchAny, MatchAny, "ON", "PARAMETER") ||
4416 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER") ||
4417 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER"))
4418 COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_alter_system_set_vars);
4419
4420 else if (TailMatches("GRANT", MatchAny, "ON", "PARAMETER", MatchAny) ||
4421 TailMatches("GRANT", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4422 COMPLETE_WITH("TO");
4423
4424 else if (TailMatches("REVOKE", MatchAny, "ON", "PARAMETER", MatchAny) ||
4425 TailMatches("REVOKE", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny) ||
4426 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "PARAMETER", MatchAny) ||
4427 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, MatchAny, "ON", "PARAMETER", MatchAny))
4428 COMPLETE_WITH("FROM");
4429
4430 /*
4431 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
4432 * TO/FROM
4433 */
4434 else if (TailMatches("GRANT|REVOKE", MatchAny) ||
4435 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny))
4436 {
4437 if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|MAINTAIN|ALL"))
4438 COMPLETE_WITH("ON");
4439 else if (TailMatches("GRANT", MatchAny))
4440 COMPLETE_WITH("TO");
4441 else
4442 COMPLETE_WITH("FROM");
4443 }
4444
4445 /*
4446 * Complete GRANT/REVOKE <sth> ON with a list of appropriate relations.
4447 *
4448 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
4449 * here will only work if the privilege list contains exactly one
4450 * privilege.
4451 */
4452 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON") ||
4453 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON"))
4454 {
4455 /*
4456 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
4457 * objects supported.
4458 */
4459 if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
4460 COMPLETE_WITH("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS");
4461 else
4462 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_grantables,
4463 "ALL FUNCTIONS IN SCHEMA",
4464 "ALL PROCEDURES IN SCHEMA",
4465 "ALL ROUTINES IN SCHEMA",
4466 "ALL SEQUENCES IN SCHEMA",
4467 "ALL TABLES IN SCHEMA",
4468 "DATABASE",
4469 "DOMAIN",
4470 "FOREIGN DATA WRAPPER",
4471 "FOREIGN SERVER",
4472 "FUNCTION",
4473 "LANGUAGE",
4474 "LARGE OBJECT",
4475 "PARAMETER",
4476 "PROCEDURE",
4477 "ROUTINE",
4478 "SCHEMA",
4479 "SEQUENCE",
4480 "TABLE",
4481 "TABLESPACE",
4482 "TYPE");
4483 }
4484 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
4485 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
4486 COMPLETE_WITH("FUNCTIONS IN SCHEMA",
4487 "PROCEDURES IN SCHEMA",
4488 "ROUTINES IN SCHEMA",
4489 "SEQUENCES IN SCHEMA",
4490 "TABLES IN SCHEMA");
4491 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN") ||
4492 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN"))
4493 COMPLETE_WITH("DATA WRAPPER", "SERVER");
4494
4495 /*
4496 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
4497 * appropriate objects.
4498 *
4499 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
4500 */
4501 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny) ||
4502 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny))
4503 {
4504 if (TailMatches("DATABASE"))
4505 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
4506 else if (TailMatches("DOMAIN"))
4507 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
4508 else if (TailMatches("FUNCTION"))
4509 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
4510 else if (TailMatches("LANGUAGE"))
4511 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
4512 else if (TailMatches("PROCEDURE"))
4513 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures);
4514 else if (TailMatches("ROUTINE"))
4515 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
4516 else if (TailMatches("SCHEMA"))
4517 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
4518 else if (TailMatches("SEQUENCE"))
4519 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
4520 else if (TailMatches("TABLE"))
4521 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_grantables);
4522 else if (TailMatches("TABLESPACE"))
4523 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
4524 else if (TailMatches("TYPE"))
4525 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
4526 else if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny))
4527 COMPLETE_WITH("TO");
4528 else
4529 COMPLETE_WITH("FROM");
4530 }
4531
4532 /*
4533 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
4534 * CURRENT_ROLE, CURRENT_USER, or SESSION_USER.
4535 */
4536 else if (Matches("GRANT", MatchAnyN, "TO") ||
4537 Matches("REVOKE", MatchAnyN, "FROM"))
4538 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4539 Keywords_for_list_of_grant_roles);
4540
4541 /*
4542 * Offer grant options after that.
4543 */
4544 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny))
4545 COMPLETE_WITH("WITH ADMIN",
4546 "WITH INHERIT",
4547 "WITH SET",
4548 "WITH GRANT OPTION",
4549 "GRANTED BY");
4550 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH"))
4551 COMPLETE_WITH("ADMIN",
4552 "INHERIT",
4553 "SET",
4554 "GRANT OPTION");
4555 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", "ADMIN|INHERIT|SET"))
4556 COMPLETE_WITH("OPTION", "TRUE", "FALSE");
4557 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION"))
4558 COMPLETE_WITH("GRANTED BY");
4559 else if (Matches("GRANT", MatchAnyN, "TO", MatchAny, "WITH", MatchAny, "OPTION", "GRANTED", "BY"))
4560 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4561 Keywords_for_list_of_grant_roles);
4562 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
4563 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO|FROM"))
4564 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4565 Keywords_for_list_of_grant_roles);
4566 /* Offer WITH GRANT OPTION after that */
4567 else if (Matches("ALTER", "DEFAULT", "PRIVILEGES", MatchAnyN, "TO", MatchAny))
4568 COMPLETE_WITH("WITH GRANT OPTION");
4569 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
4570 else if (Matches("GRANT", MatchAnyN, "ON", MatchAny, MatchAny))
4571 COMPLETE_WITH("TO");
4572 else if (Matches("REVOKE", MatchAnyN, "ON", MatchAny, MatchAny))
4573 COMPLETE_WITH("FROM");
4574
4575 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
4576 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
4577 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
4578 {
4579 if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
4580 COMPLETE_WITH("TO");
4581 else
4582 COMPLETE_WITH("FROM");
4583 }
4584
4585 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
4586 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
4587 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
4588 {
4589 if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
4590 COMPLETE_WITH("TO");
4591 else
4592 COMPLETE_WITH("FROM");
4593 }
4594
4595 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
4596 else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
4597 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
4598 {
4599 if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
4600 COMPLETE_WITH("TO");
4601 else
4602 COMPLETE_WITH("FROM");
4603 }
4604
4605/* GROUP BY */
4606 else if (TailMatches("FROM", MatchAny, "GROUP"))
4607 COMPLETE_WITH("BY");
4608
4609/* IMPORT FOREIGN SCHEMA */
4610 else if (Matches("IMPORT"))
4611 COMPLETE_WITH("FOREIGN SCHEMA");
4612 else if (Matches("IMPORT", "FOREIGN"))
4613 COMPLETE_WITH("SCHEMA");
4614 else if (Matches("IMPORT", "FOREIGN", "SCHEMA", MatchAny))
4615 COMPLETE_WITH("EXCEPT (", "FROM SERVER", "LIMIT TO (");
4616 else if (TailMatches("LIMIT", "TO", "(*)") ||
4617 TailMatches("EXCEPT", "(*)"))
4618 COMPLETE_WITH("FROM SERVER");
4619 else if (TailMatches("FROM", "SERVER", MatchAny))
4620 COMPLETE_WITH("INTO");
4621 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO"))
4622 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
4623 else if (TailMatches("FROM", "SERVER", MatchAny, "INTO", MatchAny))
4624 COMPLETE_WITH("OPTIONS (");
4625
4626/* INSERT --- can be inside EXPLAIN, RULE, etc */
4627 /* Complete NOT MATCHED THEN INSERT */
4628 else if (TailMatches("NOT", "MATCHED", "THEN", "INSERT"))
4629 COMPLETE_WITH("VALUES", "(");
4630 /* Complete INSERT with "INTO" */
4631 else if (TailMatches("INSERT"))
4632 COMPLETE_WITH("INTO");
4633 /* Complete INSERT INTO with table names */
4634 else if (TailMatches("INSERT", "INTO"))
4635 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
4636 /* Complete "INSERT INTO <table> (" with attribute names */
4637 else if (TailMatches("INSERT", "INTO", MatchAny, "("))
4638 COMPLETE_WITH_ATTR(prev2_wd);
4639
4640 /*
4641 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
4642 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
4643 */
4644 else if (TailMatches("INSERT", "INTO", MatchAny))
4645 COMPLETE_WITH("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
4646
4647 /*
4648 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
4649 * "TABLE" or "OVERRIDING"
4650 */
4651 else if (TailMatches("INSERT", "INTO", MatchAny, MatchAny) &&
4652 ends_with(prev_wd, ')'))
4653 COMPLETE_WITH("SELECT", "TABLE", "VALUES", "OVERRIDING");
4654
4655 /* Complete OVERRIDING */
4656 else if (TailMatches("OVERRIDING"))
4657 COMPLETE_WITH("SYSTEM VALUE", "USER VALUE");
4658
4659 /* Complete after OVERRIDING clause */
4660 else if (TailMatches("OVERRIDING", MatchAny, "VALUE"))
4661 COMPLETE_WITH("SELECT", "TABLE", "VALUES");
4662
4663 /* Insert an open parenthesis after "VALUES" */
4664 else if (TailMatches("VALUES") && !TailMatches("DEFAULT", "VALUES"))
4665 COMPLETE_WITH("(");
4666
4667/* LOCK */
4668 /* Complete LOCK [TABLE] [ONLY] with a list of tables */
4669 else if (Matches("LOCK"))
4670 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
4671 "TABLE", "ONLY");
4672 else if (Matches("LOCK", "TABLE"))
4673 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_tables,
4674 "ONLY");
4675 else if (Matches("LOCK", "TABLE", "ONLY") || Matches("LOCK", "ONLY"))
4676 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
4677 /* For the following, handle the case of a single table only for now */
4678
4679 /* Complete LOCK [TABLE] [ONLY] <table> with IN or NOWAIT */
4680 else if (Matches("LOCK", MatchAnyExcept("TABLE|ONLY")) ||
4681 Matches("LOCK", "TABLE", MatchAnyExcept("ONLY")) ||
4682 Matches("LOCK", "ONLY", MatchAny) ||
4683 Matches("LOCK", "TABLE", "ONLY", MatchAny))
4684 COMPLETE_WITH("IN", "NOWAIT");
4685
4686 /* Complete LOCK [TABLE] [ONLY] <table> IN with a lock mode */
4687 else if (Matches("LOCK", MatchAnyN, "IN"))
4688 COMPLETE_WITH("ACCESS SHARE MODE",
4689 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
4690 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
4691 "SHARE ROW EXCLUSIVE MODE",
4692 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
4693
4694 /*
4695 * Complete LOCK [TABLE][ONLY] <table> IN ACCESS|ROW with rest of lock
4696 * mode
4697 */
4698 else if (Matches("LOCK", MatchAnyN, "IN", "ACCESS|ROW"))
4699 COMPLETE_WITH("EXCLUSIVE MODE", "SHARE MODE");
4700
4701 /* Complete LOCK [TABLE] [ONLY] <table> IN SHARE with rest of lock mode */
4702 else if (Matches("LOCK", MatchAnyN, "IN", "SHARE"))
4703 COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE",
4704 "UPDATE EXCLUSIVE MODE");
4705
4706 /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with "NOWAIT" */
4707 else if (Matches("LOCK", MatchAnyN, "MODE"))
4708 COMPLETE_WITH("NOWAIT");
4709
4710/* MERGE --- can be inside EXPLAIN */
4711 else if (TailMatches("MERGE"))
4712 COMPLETE_WITH("INTO");
4713 else if (TailMatches("MERGE", "INTO"))
4714 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_mergetargets);
4715
4716 /* Complete MERGE INTO <table> [[AS] <alias>] with USING */
4717 else if (TailMatches("MERGE", "INTO", MatchAny))
4718 COMPLETE_WITH("USING", "AS");
4719 else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
4720 TailMatches("MERGE", "INTO", MatchAny, MatchAnyExcept("USING|AS")))
4721 COMPLETE_WITH("USING");
4722
4723 /*
4724 * Complete MERGE INTO ... USING with a list of relations supporting
4725 * SELECT
4726 */
4727 else if (TailMatches("MERGE", "INTO", MatchAny, "USING") ||
4728 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING") ||
4729 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING"))
4730 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
4731
4732 /*
4733 * Complete MERGE INTO <table> [[AS] <alias>] USING <relations> [[AS]
4734 * alias] with ON
4735 */
4736 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny) ||
4737 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny) ||
4738 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny))
4739 COMPLETE_WITH("AS", "ON");
4740 else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
4741 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny) ||
4742 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, "AS", MatchAny) ||
4743 TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
4744 TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")) ||
4745 TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAnyExcept("ON|AS")))
4746 COMPLETE_WITH("ON");
4747
4748 /* Complete MERGE INTO ... ON with target table attributes */
4749 else if (TailMatches("INTO", MatchAny, "USING", MatchAny, "ON"))
4750 COMPLETE_WITH_ATTR(prev4_wd);
4751 else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", MatchAny, "AS", MatchAny, "ON"))
4752 COMPLETE_WITH_ATTR(prev8_wd);
4753 else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, MatchAny, "ON"))
4754 COMPLETE_WITH_ATTR(prev6_wd);
4755
4756 /*
4757 * Complete ... USING <relation> [[AS] alias] ON join condition
4758 * (consisting of one or three words typically used) with WHEN [NOT]
4759 * MATCHED
4760 */
4761 else if (TailMatches("USING", MatchAny, "ON", MatchAny) ||
4762 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny) ||
4763 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny) ||
4764 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
4765 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
4766 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")))
4767 COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
4768 else if (TailMatches("USING", MatchAny, "ON", MatchAny, "WHEN") ||
4769 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, "WHEN") ||
4770 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, "WHEN") ||
4771 TailMatches("USING", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
4772 TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN") ||
4773 TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny, MatchAny, MatchAny, "WHEN"))
4774 COMPLETE_WITH("MATCHED", "NOT MATCHED");
4775
4776 /*
4777 * Complete ... WHEN MATCHED and WHEN NOT MATCHED BY SOURCE|TARGET with
4778 * THEN/AND
4779 */
4780 else if (TailMatches("WHEN", "MATCHED") ||
4781 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE|TARGET"))
4782 COMPLETE_WITH("THEN", "AND");
4783
4784 /* Complete ... WHEN NOT MATCHED with BY/THEN/AND */
4785 else if (TailMatches("WHEN", "NOT", "MATCHED"))
4786 COMPLETE_WITH("BY", "THEN", "AND");
4787
4788 /* Complete ... WHEN NOT MATCHED BY with SOURCE/TARGET */
4789 else if (TailMatches("WHEN", "NOT", "MATCHED", "BY"))
4790 COMPLETE_WITH("SOURCE", "TARGET");
4791
4792 /*
4793 * Complete ... WHEN MATCHED THEN and WHEN NOT MATCHED BY SOURCE THEN with
4794 * UPDATE SET/DELETE/DO NOTHING
4795 */
4796 else if (TailMatches("WHEN", "MATCHED", "THEN") ||
4797 TailMatches("WHEN", "NOT", "MATCHED", "BY", "SOURCE", "THEN"))
4798 COMPLETE_WITH("UPDATE SET", "DELETE", "DO NOTHING");
4799
4800 /*
4801 * Complete ... WHEN NOT MATCHED [BY TARGET] THEN with INSERT/DO NOTHING
4802 */
4803 else if (TailMatches("WHEN", "NOT", "MATCHED", "THEN") ||
4804 TailMatches("WHEN", "NOT", "MATCHED", "BY", "TARGET", "THEN"))
4805 COMPLETE_WITH("INSERT", "DO NOTHING");
4806
4807/* NOTIFY --- can be inside EXPLAIN, RULE, etc */
4808 else if (TailMatches("NOTIFY"))
4809 COMPLETE_WITH_QUERY(Query_for_list_of_channels);
4810
4811/* OPTIONS */
4812 else if (TailMatches("OPTIONS"))
4813 COMPLETE_WITH("(");
4814
4815/* OWNER TO - complete with available roles */
4816 else if (TailMatches("OWNER", "TO"))
4817 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
4818 Keywords_for_list_of_owner_roles);
4819
4820/* ORDER BY */
4821 else if (TailMatches("FROM", MatchAny, "ORDER"))
4822 COMPLETE_WITH("BY");
4823 else if (TailMatches("FROM", MatchAny, "ORDER", "BY"))
4824 COMPLETE_WITH_ATTR(prev3_wd);
4825
4826/* PREPARE xx AS */
4827 else if (Matches("PREPARE", MatchAny, "AS"))
4828 COMPLETE_WITH("SELECT", "UPDATE", "INSERT INTO", "DELETE FROM");
4829
4830/*
4831 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
4832 * managers, not for manual use in interactive sessions.
4833 */
4834
4835/* REASSIGN OWNED BY xxx TO yyy */
4836 else if (Matches("REASSIGN"))
4837 COMPLETE_WITH("OWNED BY");
4838 else if (Matches("REASSIGN", "OWNED"))
4839 COMPLETE_WITH("BY");
4840 else if (Matches("REASSIGN", "OWNED", "BY"))
4841 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
4842 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny))
4843 COMPLETE_WITH("TO");
4844 else if (Matches("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
4845 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
4846
4847/* REFRESH MATERIALIZED VIEW */
4848 else if (Matches("REFRESH"))
4849 COMPLETE_WITH("MATERIALIZED VIEW");
4850 else if (Matches("REFRESH", "MATERIALIZED"))
4851 COMPLETE_WITH("VIEW");
4852 else if (Matches("REFRESH", "MATERIALIZED", "VIEW"))
4853 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_matviews,
4854 "CONCURRENTLY");
4855 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
4856 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
4857 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
4858 COMPLETE_WITH("WITH");
4859 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
4860 COMPLETE_WITH("WITH");
4861 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
4862 COMPLETE_WITH("NO DATA", "DATA");
4863 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
4864 COMPLETE_WITH("NO DATA", "DATA");
4865 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
4866 COMPLETE_WITH("DATA");
4867 else if (Matches("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
4868 COMPLETE_WITH("DATA");
4869
4870/* REINDEX */
4871 else if (Matches("REINDEX") ||
4872 Matches("REINDEX", "(*)"))
4873 COMPLETE_WITH("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
4874 else if (Matches("REINDEX", "TABLE") ||
4875 Matches("REINDEX", "(*)", "TABLE"))
4876 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexables,
4877 "CONCURRENTLY");
4878 else if (Matches("REINDEX", "INDEX") ||
4879 Matches("REINDEX", "(*)", "INDEX"))
4880 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_indexes,
4881 "CONCURRENTLY");
4882 else if (Matches("REINDEX", "SCHEMA") ||
4883 Matches("REINDEX", "(*)", "SCHEMA"))
4884 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas,
4885 "CONCURRENTLY");
4886 else if (Matches("REINDEX", "SYSTEM|DATABASE") ||
4887 Matches("REINDEX", "(*)", "SYSTEM|DATABASE"))
4888 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_databases,
4889 "CONCURRENTLY");
4890 else if (Matches("REINDEX", "TABLE", "CONCURRENTLY") ||
4891 Matches("REINDEX", "(*)", "TABLE", "CONCURRENTLY"))
4892 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexables);
4893 else if (Matches("REINDEX", "INDEX", "CONCURRENTLY") ||
4894 Matches("REINDEX", "(*)", "INDEX", "CONCURRENTLY"))
4895 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
4896 else if (Matches("REINDEX", "SCHEMA", "CONCURRENTLY") ||
4897 Matches("REINDEX", "(*)", "SCHEMA", "CONCURRENTLY"))
4898 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
4899 else if (Matches("REINDEX", "SYSTEM|DATABASE", "CONCURRENTLY") ||
4900 Matches("REINDEX", "(*)", "SYSTEM|DATABASE", "CONCURRENTLY"))
4901 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
4902 else if (HeadMatches("REINDEX", "(*") &&
4903 !HeadMatches("REINDEX", "(*)"))
4904 {
4905 /*
4906 * This fires if we're in an unfinished parenthesized option list.
4907 * get_previous_words treats a completed parenthesized option list as
4908 * one word, so the above test is correct.
4909 */
4910 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
4911 COMPLETE_WITH("CONCURRENTLY", "TABLESPACE", "VERBOSE");
4912 else if (TailMatches("TABLESPACE"))
4913 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
4914 }
4915
4916/* SECURITY LABEL */
4917 else if (Matches("SECURITY"))
4918 COMPLETE_WITH("LABEL");
4919 else if (Matches("SECURITY", "LABEL"))
4920 COMPLETE_WITH("ON", "FOR");
4921 else if (Matches("SECURITY", "LABEL", "FOR", MatchAny))
4922 COMPLETE_WITH("ON");
4923 else if (Matches("SECURITY", "LABEL", "ON") ||
4924 Matches("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
4925 COMPLETE_WITH("TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
4926 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION",
4927 "LARGE OBJECT", "MATERIALIZED VIEW", "LANGUAGE",
4928 "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
4929 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW");
4930 else if (Matches("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
4931 COMPLETE_WITH("IS");
4932
4933/* SELECT */
4934 /* naah . . . */
4935
4936/* SET, RESET, SHOW */
4937 /* Complete with a variable name */
4938 else if (TailMatches("SET|RESET") &&
4939 !TailMatches("UPDATE", MatchAny, "SET") &&
4940 !TailMatches("ALTER", "DATABASE", MatchAny, "RESET"))
4941 COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
4942 "CONSTRAINTS",
4943 "TRANSACTION",
4944 "SESSION",
4945 "ROLE",
4946 "TABLESPACE",
4947 "ALL");
4948 else if (Matches("SHOW"))
4949 COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_show_vars,
4950 "SESSION AUTHORIZATION",
4951 "ALL");
4952 else if (Matches("SHOW", "SESSION"))
4953 COMPLETE_WITH("AUTHORIZATION");
4954 /* Complete "SET TRANSACTION" */
4955 else if (Matches("SET", "TRANSACTION"))
4956 COMPLETE_WITH("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
4957 else if (Matches("BEGIN|START", "TRANSACTION") ||
4958 Matches("BEGIN", "WORK") ||
4959 Matches("BEGIN") ||
4960 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
4961 COMPLETE_WITH("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
4962 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
4963 Matches("BEGIN", "NOT") ||
4964 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
4965 COMPLETE_WITH("DEFERRABLE");
4966 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
4967 Matches("BEGIN", "ISOLATION") ||
4968 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
4969 COMPLETE_WITH("LEVEL");
4970 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
4971 Matches("BEGIN", "ISOLATION", "LEVEL") ||
4972 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
4973 COMPLETE_WITH("READ", "REPEATABLE READ", "SERIALIZABLE");
4974 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
4975 Matches("BEGIN", "ISOLATION", "LEVEL", "READ") ||
4976 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
4977 COMPLETE_WITH("UNCOMMITTED", "COMMITTED");
4978 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
4979 Matches("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
4980 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
4981 COMPLETE_WITH("READ");
4982 else if (Matches("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
4983 Matches("BEGIN", "READ") ||
4984 Matches("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
4985 COMPLETE_WITH("ONLY", "WRITE");
4986 /* SET CONSTRAINTS */
4987 else if (Matches("SET", "CONSTRAINTS"))
4988 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_constraints_with_schema,
4989 "ALL");
4990 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
4991 else if (Matches("SET", "CONSTRAINTS", MatchAny))
4992 COMPLETE_WITH("DEFERRED", "IMMEDIATE");
4993 /* Complete SET ROLE */
4994 else if (Matches("SET", "ROLE"))
4995 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
4996 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
4997 else if (Matches("SET", "SESSION"))
4998 COMPLETE_WITH("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
4999 /* Complete SET SESSION AUTHORIZATION with username */
5000 else if (Matches("SET", "SESSION", "AUTHORIZATION"))
5001 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
5002 "DEFAULT");
5003 /* Complete RESET SESSION with AUTHORIZATION */
5004 else if (Matches("RESET", "SESSION"))
5005 COMPLETE_WITH("AUTHORIZATION");
5006 /* Complete SET <var> with "TO" */
5007 else if (Matches("SET", MatchAny))
5008 COMPLETE_WITH("TO");
5009
5010 /*
5011 * Complete ALTER DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER ... SET
5012 * <name>
5013 */
5014 else if (Matches("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER", MatchAnyN, "SET", MatchAnyExcept("SCHEMA")))
5015 COMPLETE_WITH("FROM CURRENT", "TO");
5016
5017 /*
5018 * Suggest possible variable values in SET variable TO|=, along with the
5019 * preceding ALTER syntaxes.
5020 */
5021 else if (TailMatches("SET", MatchAny, "TO|=") &&
5022 !TailMatches("UPDATE", MatchAny, "SET", MatchAny, "TO|="))
5023 {
5024 /* special cased code for individual GUCs */
5025 if (TailMatches("DateStyle", "TO|="))
5026 COMPLETE_WITH("ISO", "SQL", "Postgres", "German",
5027 "YMD", "DMY", "MDY",
5028 "US", "European", "NonEuropean",
5029 "DEFAULT");
5030 else if (TailMatches("search_path", "TO|="))
5031 {
5032 /* Here, we want to allow pg_catalog, so use narrower exclusion */
5033 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas
5034 " AND nspname NOT LIKE E'pg\\\\_toast%%'"
5035 " AND nspname NOT LIKE E'pg\\\\_temp%%'",
5036 "DEFAULT");
5037 }
5038 else if (TailMatches("TimeZone", "TO|="))
5039 COMPLETE_WITH_TIMEZONE_NAME();
5040 else
5041 {
5042 /* generic, type based, GUC support */
5043 char *guctype = get_guctype(prev2_wd);
5044
5045 /*
5046 * Note: if we don't recognize the GUC name, it's important to not
5047 * offer any completions, as most likely we've misinterpreted the
5048 * context and this isn't a GUC-setting command at all.
5049 */
5050 if (guctype)
5051 {
5052 if (strcmp(guctype, "enum") == 0)
5053 {
5054 set_completion_reference_verbatim(prev2_wd);
5055 COMPLETE_WITH_QUERY_PLUS(Query_for_values_of_enum_GUC,
5056 "DEFAULT");
5057 }
5058 else if (strcmp(guctype, "bool") == 0)
5059 COMPLETE_WITH("on", "off", "true", "false", "yes", "no",
5060 "1", "0", "DEFAULT");
5061 else
5062 COMPLETE_WITH("DEFAULT");
5063
5064 free(guctype);
5065 }
5066 }
5067 }
5068
5069/* START TRANSACTION */
5070 else if (Matches("START"))
5071 COMPLETE_WITH("TRANSACTION");
5072
5073/* TABLE, but not TABLE embedded in other commands */
5074 else if (Matches("TABLE"))
5075 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
5076
5077/* TABLESAMPLE */
5078 else if (TailMatches("TABLESAMPLE"))
5079 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
5080 else if (TailMatches("TABLESAMPLE", MatchAny))
5081 COMPLETE_WITH("(");
5082
5083/* TRUNCATE */
5084 else if (Matches("TRUNCATE"))
5085 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_truncatables,
5086 "TABLE", "ONLY");
5087 else if (Matches("TRUNCATE", "TABLE"))
5088 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_truncatables,
5089 "ONLY");
5090 else if (Matches("TRUNCATE", MatchAnyN, "ONLY"))
5091 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_truncatables);
5092 else if (Matches("TRUNCATE", MatchAny) ||
5093 Matches("TRUNCATE", "TABLE|ONLY", MatchAny) ||
5094 Matches("TRUNCATE", "TABLE", "ONLY", MatchAny))
5095 COMPLETE_WITH("RESTART IDENTITY", "CONTINUE IDENTITY", "CASCADE", "RESTRICT");
5096 else if (Matches("TRUNCATE", MatchAnyN, "IDENTITY"))
5097 COMPLETE_WITH("CASCADE", "RESTRICT");
5098
5099/* UNLISTEN */
5100 else if (Matches("UNLISTEN"))
5101 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_channels, "*");
5102
5103/* UPDATE --- can be inside EXPLAIN, RULE, etc */
5104 /* If prev. word is UPDATE suggest a list of tables */
5105 else if (TailMatches("UPDATE"))
5106 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
5107 /* Complete UPDATE <table> with "SET" */
5108 else if (TailMatches("UPDATE", MatchAny))
5109 COMPLETE_WITH("SET");
5110 /* Complete UPDATE <table> SET with list of attributes */
5111 else if (TailMatches("UPDATE", MatchAny, "SET"))
5112 COMPLETE_WITH_ATTR(prev2_wd);
5113 /* UPDATE <table> SET <attr> = */
5114 else if (TailMatches("UPDATE", MatchAny, "SET", MatchAnyExcept("*=")))
5115 COMPLETE_WITH("=");
5116
5117/* USER MAPPING */
5118 else if (Matches("ALTER|CREATE|DROP", "USER", "MAPPING"))
5119 COMPLETE_WITH("FOR");
5120 else if (Matches("CREATE", "USER", "MAPPING", "FOR"))
5121 COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
5122 "CURRENT_ROLE",
5123 "CURRENT_USER",
5124 "PUBLIC",
5125 "USER");
5126 else if (Matches("ALTER|DROP", "USER", "MAPPING", "FOR"))
5127 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
5128 else if (Matches("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
5129 COMPLETE_WITH("SERVER");
5130 else if (Matches("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
5131 COMPLETE_WITH("OPTIONS");
5132
5133/*
5134 * VACUUM [ ( option [, ...] ) ] [ [ ONLY ] table_and_columns [, ...] ]
5135 * VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ [ ONLY ] table_and_columns [, ...] ]
5136 */
5137 else if (Matches("VACUUM"))
5138 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
5139 "(",
5140 "FULL",
5141 "FREEZE",
5142 "VERBOSE",
5143 "ANALYZE",
5144 "ONLY");
5145 else if (Matches("VACUUM", "FULL"))
5146 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
5147 "FREEZE",
5148 "VERBOSE",
5149 "ANALYZE",
5150 "ONLY");
5151 else if (Matches("VACUUM", MatchAnyN, "FREEZE"))
5152 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
5153 "VERBOSE",
5154 "ANALYZE",
5155 "ONLY");
5156 else if (Matches("VACUUM", MatchAnyN, "VERBOSE"))
5157 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
5158 "ANALYZE",
5159 "ONLY");
5160 else if (Matches("VACUUM", MatchAnyN, "ANALYZE"))
5161 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_vacuumables,
5162 "ONLY");
5163 else if (HeadMatches("VACUUM", "(*") &&
5164 !HeadMatches("VACUUM", "(*)"))
5165 {
5166 /*
5167 * This fires if we're in an unfinished parenthesized option list.
5168 * get_previous_words treats a completed parenthesized option list as
5169 * one word, so the above test is correct.
5170 */
5171 if (ends_with(prev_wd, '(') || ends_with(prev_wd, ','))
5172 COMPLETE_WITH("FULL", "FREEZE", "ANALYZE", "VERBOSE",
5173 "DISABLE_PAGE_SKIPPING", "SKIP_LOCKED",
5174 "INDEX_CLEANUP", "PROCESS_MAIN", "PROCESS_TOAST",
5175 "TRUNCATE", "PARALLEL", "SKIP_DATABASE_STATS",
5176 "ONLY_DATABASE_STATS", "BUFFER_USAGE_LIMIT");
5177 else if (TailMatches("FULL|FREEZE|ANALYZE|VERBOSE|DISABLE_PAGE_SKIPPING|SKIP_LOCKED|PROCESS_MAIN|PROCESS_TOAST|TRUNCATE|SKIP_DATABASE_STATS|ONLY_DATABASE_STATS"))
5178 COMPLETE_WITH("ON", "OFF");
5179 else if (TailMatches("INDEX_CLEANUP"))
5180 COMPLETE_WITH("AUTO", "ON", "OFF");
5181 }
5182 else if (Matches("VACUUM", MatchAnyN, "("))
5183 /* "VACUUM (" should be caught above, so assume we want columns */
5184 COMPLETE_WITH_ATTR(prev2_wd);
5185 else if (HeadMatches("VACUUM"))
5186 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_vacuumables);
5187
5188/* WITH [RECURSIVE] */
5189
5190 /*
5191 * Only match when WITH is the first word, as WITH may appear in many
5192 * other contexts.
5193 */
5194 else if (Matches("WITH"))
5195 COMPLETE_WITH("RECURSIVE");
5196
5197/* WHERE */
5198 /* Simple case of the word before the where being the table name */
5199 else if (TailMatches(MatchAny, "WHERE"))
5200 COMPLETE_WITH_ATTR(prev2_wd);
5201
5202/* ... FROM ... */
5203/* TODO: also include SRF ? */
5204 else if (TailMatches("FROM") && !Matches("COPY|\\copy", MatchAny, "FROM"))
5205 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
5206
5207/* ... JOIN ... */
5208 else if (TailMatches("JOIN"))
5209 COMPLETE_WITH_SCHEMA_QUERY_PLUS(Query_for_list_of_selectables, "LATERAL");
5210 else if (TailMatches("JOIN", MatchAny) && !TailMatches("CROSS|NATURAL", "JOIN", MatchAny))
5211 COMPLETE_WITH("ON", "USING (");
5212 else if (TailMatches("JOIN", MatchAny, MatchAny) &&
5213 !TailMatches("CROSS|NATURAL", "JOIN", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5214 COMPLETE_WITH("ON", "USING (");
5215 else if (TailMatches("JOIN", "LATERAL", MatchAny, MatchAny) &&
5216 !TailMatches("CROSS|NATURAL", "JOIN", "LATERAL", MatchAny, MatchAny) && !TailMatches("ON|USING"))
5217 COMPLETE_WITH("ON", "USING (");
5218 else if (TailMatches("JOIN", MatchAny, "USING") ||
5219 TailMatches("JOIN", MatchAny, MatchAny, "USING") ||
5220 TailMatches("JOIN", "LATERAL", MatchAny, MatchAny, "USING"))
5221 COMPLETE_WITH("(");
5222 else if (TailMatches("JOIN", MatchAny, "USING", "("))
5223 COMPLETE_WITH_ATTR(prev3_wd);
5224 else if (TailMatches("JOIN", MatchAny, MatchAny, "USING", "("))
5225 COMPLETE_WITH_ATTR(prev4_wd);
5226
5227/* ... AT [ LOCAL | TIME ZONE ] ... */
5228 else if (TailMatches("AT"))
5229 COMPLETE_WITH("LOCAL", "TIME ZONE");
5230 else if (TailMatches("AT", "TIME", "ZONE"))
5231 COMPLETE_WITH_TIMEZONE_NAME();
5232
5233/* Backslash commands */
5234/* TODO: \dc \dd \dl */
5235 else if (TailMatchesCS("\\?"))
5236 COMPLETE_WITH_CS("commands", "options", "variables");
5237 else if (TailMatchesCS("\\connect|\\c"))
5238 {
5240 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
5241 }
5242 else if (TailMatchesCS("\\connect|\\c", MatchAny))
5243 {
5244 if (!recognized_connection_string(prev_wd))
5245 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
5246 }
5247 else if (TailMatchesCS("\\da*"))
5248 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates);
5249 else if (TailMatchesCS("\\dAc*", MatchAny) ||
5250 TailMatchesCS("\\dAf*", MatchAny))
5251 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
5252 else if (TailMatchesCS("\\dAo*", MatchAny) ||
5253 TailMatchesCS("\\dAp*", MatchAny))
5254 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_operator_families);
5255 else if (TailMatchesCS("\\dA*"))
5256 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
5257 else if (TailMatchesCS("\\db*"))
5258 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
5259 else if (TailMatchesCS("\\dconfig*"))
5260 COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_show_vars);
5261 else if (TailMatchesCS("\\dD*"))
5262 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
5263 else if (TailMatchesCS("\\des*"))
5264 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
5265 else if (TailMatchesCS("\\deu*"))
5266 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
5267 else if (TailMatchesCS("\\dew*"))
5268 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
5269 else if (TailMatchesCS("\\df*"))
5270 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions);
5271 else if (HeadMatchesCS("\\df*"))
5272 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
5273
5274 else if (TailMatchesCS("\\dFd*"))
5275 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_dictionaries);
5276 else if (TailMatchesCS("\\dFp*"))
5277 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_parsers);
5278 else if (TailMatchesCS("\\dFt*"))
5279 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_templates);
5280 /* must be at end of \dF alternatives: */
5281 else if (TailMatchesCS("\\dF*"))
5282 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_ts_configurations);
5283
5284 else if (TailMatchesCS("\\di*"))
5285 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
5286 else if (TailMatchesCS("\\dL*"))
5287 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
5288 else if (TailMatchesCS("\\dn*"))
5289 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
5290 /* no support for completing operators, but we can complete types: */
5291 else if (HeadMatchesCS("\\do*", MatchAny))
5292 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
5293 else if (TailMatchesCS("\\dp") || TailMatchesCS("\\z"))
5294 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_grantables);
5295 else if (TailMatchesCS("\\dPi*"))
5296 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_indexes);
5297 else if (TailMatchesCS("\\dPt*"))
5298 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables);
5299 else if (TailMatchesCS("\\dP*"))
5300 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_relations);
5301 else if (TailMatchesCS("\\dRp*"))
5302 COMPLETE_WITH_VERSIONED_QUERY(Query_for_list_of_publications);
5303 else if (TailMatchesCS("\\dRs*"))
5304 COMPLETE_WITH_VERSIONED_QUERY(Query_for_list_of_subscriptions);
5305 else if (TailMatchesCS("\\ds*"))
5306 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
5307 else if (TailMatchesCS("\\dt*"))
5308 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
5309 else if (TailMatchesCS("\\dT*"))
5310 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
5311 else if (TailMatchesCS("\\du*") ||
5312 TailMatchesCS("\\dg*") ||
5313 TailMatchesCS("\\drg*"))
5314 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
5315 else if (TailMatchesCS("\\dv*"))
5316 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
5317 else if (TailMatchesCS("\\dx*"))
5318 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
5319 else if (TailMatchesCS("\\dX*"))
5320 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_statistics);
5321 else if (TailMatchesCS("\\dm*"))
5322 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
5323 else if (TailMatchesCS("\\dE*"))
5324 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
5325 else if (TailMatchesCS("\\dy*"))
5326 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
5327
5328 /* must be at end of \d alternatives: */
5329 else if (TailMatchesCS("\\d*"))
5330 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations);
5331
5332 else if (TailMatchesCS("\\ef"))
5333 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
5334 else if (TailMatchesCS("\\ev"))
5335 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
5336
5337 else if (TailMatchesCS("\\encoding"))
5338 COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_encodings);
5339 else if (TailMatchesCS("\\h|\\help"))
5340 COMPLETE_WITH_LIST(sql_commands);
5341 else if (TailMatchesCS("\\h|\\help", MatchAny))
5342 {
5343 if (TailMatches("DROP"))
5344 matches = rl_completion_matches(text, drop_command_generator);
5345 else if (TailMatches("ALTER"))
5346 matches = rl_completion_matches(text, alter_command_generator);
5347
5348 /*
5349 * CREATE is recognized by tail match elsewhere, so doesn't need to be
5350 * repeated here
5351 */
5352 }
5353 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny))
5354 {
5355 if (TailMatches("CREATE|DROP", "ACCESS"))
5356 COMPLETE_WITH("METHOD");
5357 else if (TailMatches("ALTER", "DEFAULT"))
5358 COMPLETE_WITH("PRIVILEGES");
5359 else if (TailMatches("CREATE|ALTER|DROP", "EVENT"))
5360 COMPLETE_WITH("TRIGGER");
5361 else if (TailMatches("CREATE|ALTER|DROP", "FOREIGN"))
5362 COMPLETE_WITH("DATA WRAPPER", "TABLE");
5363 else if (TailMatches("ALTER", "LARGE"))
5364 COMPLETE_WITH("OBJECT");
5365 else if (TailMatches("CREATE|ALTER|DROP", "MATERIALIZED"))
5366 COMPLETE_WITH("VIEW");
5367 else if (TailMatches("CREATE|ALTER|DROP", "TEXT"))
5368 COMPLETE_WITH("SEARCH");
5369 else if (TailMatches("CREATE|ALTER|DROP", "USER"))
5370 COMPLETE_WITH("MAPPING FOR");
5371 }
5372 else if (TailMatchesCS("\\h|\\help", MatchAny, MatchAny, MatchAny))
5373 {
5374 if (TailMatches("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
5375 COMPLETE_WITH("WRAPPER");
5376 else if (TailMatches("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
5377 COMPLETE_WITH("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
5378 else if (TailMatches("CREATE|ALTER|DROP", "USER", "MAPPING"))
5379 COMPLETE_WITH("FOR");
5380 }
5381 else if (TailMatchesCS("\\l*") && !TailMatchesCS("\\lo*"))
5382 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
5383 else if (TailMatchesCS("\\password"))
5384 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
5385 else if (TailMatchesCS("\\pset"))
5386 COMPLETE_WITH_CS("border", "columns", "csv_fieldsep", "expanded",
5387 "fieldsep", "fieldsep_zero", "footer", "format",
5388 "linestyle", "null", "numericlocale",
5389 "pager", "pager_min_lines",
5390 "recordsep", "recordsep_zero",
5391 "tableattr", "title", "tuples_only",
5392 "unicode_border_linestyle",
5393 "unicode_column_linestyle",
5394 "unicode_header_linestyle",
5395 "xheader_width");
5396 else if (TailMatchesCS("\\pset", MatchAny))
5397 {
5398 if (TailMatchesCS("format"))
5399 COMPLETE_WITH_CS("aligned", "asciidoc", "csv", "html", "latex",
5400 "latex-longtable", "troff-ms", "unaligned",
5401 "wrapped");
5402 else if (TailMatchesCS("xheader_width"))
5403 COMPLETE_WITH_CS("full", "column", "page");
5404 else if (TailMatchesCS("linestyle"))
5405 COMPLETE_WITH_CS("ascii", "old-ascii", "unicode");
5406 else if (TailMatchesCS("pager"))
5407 COMPLETE_WITH_CS("on", "off", "always");
5408 else if (TailMatchesCS("unicode_border_linestyle|"
5409 "unicode_column_linestyle|"
5410 "unicode_header_linestyle"))
5411 COMPLETE_WITH_CS("single", "double");
5412 }
5413 else if (TailMatchesCS("\\unset"))
5414 matches = complete_from_variables(text, "", "", true);
5415 else if (TailMatchesCS("\\set"))
5416 matches = complete_from_variables(text, "", "", false);
5417 else if (TailMatchesCS("\\set", MatchAny))
5418 {
5419 if (TailMatchesCS("AUTOCOMMIT|ON_ERROR_STOP|QUIET|SHOW_ALL_RESULTS|"
5420 "SINGLELINE|SINGLESTEP"))
5421 COMPLETE_WITH_CS("on", "off");
5422 else if (TailMatchesCS("COMP_KEYWORD_CASE"))
5423 COMPLETE_WITH_CS("lower", "upper",
5424 "preserve-lower", "preserve-upper");
5425 else if (TailMatchesCS("ECHO"))
5426 COMPLETE_WITH_CS("errors", "queries", "all", "none");
5427 else if (TailMatchesCS("ECHO_HIDDEN"))
5428 COMPLETE_WITH_CS("noexec", "off", "on");
5429 else if (TailMatchesCS("HISTCONTROL"))
5430 COMPLETE_WITH_CS("ignorespace", "ignoredups",
5431 "ignoreboth", "none");
5432 else if (TailMatchesCS("ON_ERROR_ROLLBACK"))
5433 COMPLETE_WITH_CS("on", "off", "interactive");
5434 else if (TailMatchesCS("SHOW_CONTEXT"))
5435 COMPLETE_WITH_CS("never", "errors", "always");
5436 else if (TailMatchesCS("VERBOSITY"))
5437 COMPLETE_WITH_CS("default", "verbose", "terse", "sqlstate");
5438 }
5439 else if (TailMatchesCS("\\sf*"))
5440 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines);
5441 else if (TailMatchesCS("\\sv*"))
5442 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
5443 else if (TailMatchesCS("\\cd|\\e|\\edit|\\g|\\gx|\\i|\\include|"
5444 "\\ir|\\include_relative|\\o|\\out|"
5445 "\\s|\\w|\\write|\\lo_import"))
5446 {
5447 completion_charp = "\\";
5448 completion_force_quote = false;
5449 matches = rl_completion_matches(text, complete_from_files);
5450 }
5451
5452 /* gen_tabcomplete.pl ends special processing here */
5453 /* END GEN_TABCOMPLETE */
5454
5455 return matches;
5456}
5457
5458
5459/*
5460 * GENERATOR FUNCTIONS
5461 *
5462 * These functions do all the actual work of completing the input. They get
5463 * passed the text so far and the count how many times they have been called
5464 * so far with the same text.
5465 * If you read the above carefully, you'll see that these don't get called
5466 * directly but through the readline interface.
5467 * The return value is expected to be the full completion of the text, going
5468 * through a list each time, or NULL if there are no more matches. The string
5469 * will be free()'d by readline, so you must run it through strdup() or
5470 * something of that sort.
5471 */
5472
5473/*
5474 * Common routine for create_command_generator and drop_command_generator.
5475 * Entries that have 'excluded' flags are not returned.
5476 */
5477static char *
5478create_or_drop_command_generator(const char *text, int state, bits32 excluded)
5479{
5480 static int list_index,
5481 string_length;
5482 const char *name;
5483
5484 /* If this is the first time for this completion, init some values */
5485 if (state == 0)
5486 {
5487 list_index = 0;
5488 string_length = strlen(text);
5489 }
5490
5491 /* find something that matches */
5492 while ((name = words_after_create[list_index++].name))
5493 {
5494 if ((pg_strncasecmp(name, text, string_length) == 0) &&
5495 !(words_after_create[list_index - 1].flags & excluded))
5496 return pg_strdup_keyword_case(name, text);
5497 }
5498 /* if nothing matches, return NULL */
5499 return NULL;
5500}
5501
5502/*
5503 * This one gives you one from a list of things you can put after CREATE
5504 * as defined above.
5505 */
5506static char *
5507create_command_generator(const char *text, int state)
5508{
5509 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
5510}
5511
5512/*
5513 * This function gives you a list of things you can put after a DROP command.
5514 */
5515static char *
5516drop_command_generator(const char *text, int state)
5517{
5518 return create_or_drop_command_generator(text, state, THING_NO_DROP);
5519}
5520
5521/*
5522 * This function gives you a list of things you can put after an ALTER command.
5523 */
5524static char *
5525alter_command_generator(const char *text, int state)
5526{
5527 return create_or_drop_command_generator(text, state, THING_NO_ALTER);
5528}
5529
5530/*
5531 * These functions generate lists using server queries.
5532 * They are all wrappers for _complete_from_query.
5533 */
5534
5535static char *
5536complete_from_query(const char *text, int state)
5537{
5538 /* query is assumed to work for any server version */
5539 return _complete_from_query(completion_charp, NULL, completion_charpp,
5540 completion_verbatim, text, state);
5541}
5542
5543static char *
5544complete_from_versioned_query(const char *text, int state)
5545{
5546 const VersionedQuery *vquery = completion_vquery;
5547
5548 /* Find appropriate array element */
5549 while (pset.sversion < vquery->min_server_version)
5550 vquery++;
5551 /* Fail completion if server is too old */
5552 if (vquery->query == NULL)
5553 return NULL;
5554
5555 return _complete_from_query(vquery->query, NULL, completion_charpp,
5556 completion_verbatim, text, state);
5557}
5558
5559static char *
5560complete_from_schema_query(const char *text, int state)
5561{
5562 /* query is assumed to work for any server version */
5563 return _complete_from_query(NULL, completion_squery, completion_charpp,
5564 completion_verbatim, text, state);
5565}
5566
5567static char *
5568complete_from_versioned_schema_query(const char *text, int state)
5569{
5570 const SchemaQuery *squery = completion_squery;
5571
5572 /* Find appropriate array element */
5573 while (pset.sversion < squery->min_server_version)
5574 squery++;
5575 /* Fail completion if server is too old */
5576 if (squery->catname == NULL)
5577 return NULL;
5578
5579 return _complete_from_query(NULL, squery, completion_charpp,
5580 completion_verbatim, text, state);
5581}
5582
5583
5584/*
5585 * This creates a list of matching things, according to a query described by
5586 * the initial arguments. The caller has already done any work needed to
5587 * select the appropriate query for the server's version.
5588 *
5589 * The query can be one of two kinds:
5590 *
5591 * 1. A simple query, which must contain a restriction clause of the form
5592 * output LIKE '%s'
5593 * where "output" is the same string that the query returns. The %s
5594 * will be replaced by a LIKE pattern to match the already-typed text.
5595 * There can be a second '%s', which will be replaced by a suitably-escaped
5596 * version of the string provided in completion_ref_object. If there is a
5597 * third '%s', it will be replaced by a suitably-escaped version of the string
5598 * provided in completion_ref_schema. Those strings should be set up
5599 * by calling set_completion_reference or set_completion_reference_verbatim.
5600 * Simple queries should return a single column of matches. If "verbatim"
5601 * is true, the matches are returned as-is; otherwise, they are taken to
5602 * be SQL identifiers and quoted if necessary.
5603 *
5604 * 2. A schema query used for completion of both schema and relation names.
5605 * This is represented by a SchemaQuery object; see that typedef for details.
5606 *
5607 * See top of file for examples of both kinds of query.
5608 *
5609 * In addition to the query itself, we accept a null-terminated array of
5610 * literal keywords, which will be returned if they match the input-so-far
5611 * (case insensitively). (These are in addition to keywords specified
5612 * within the schema_query, if any.)
5613 *
5614 * If "verbatim" is true, then we use the given text as-is to match the
5615 * query results; otherwise we parse it as a possibly-qualified identifier,
5616 * and reconstruct suitable quoting afterward.
5617 *
5618 * "text" and "state" are supplied by Readline. "text" is the word we are
5619 * trying to complete. "state" is zero on first call, nonzero later.
5620 *
5621 * readline will call this repeatedly with the same text and varying
5622 * state. On each call, we are supposed to return a malloc'd string
5623 * that is a candidate completion. Return NULL when done.
5624 */
5625static char *
5626_complete_from_query(const char *simple_query,
5627 const SchemaQuery *schema_query,
5628 const char *const *keywords,
5629 bool verbatim,
5630 const char *text, int state)
5631{
5632 static int list_index,
5633 num_schema_only,
5634 num_query_other,
5635 num_keywords;
5636 static PGresult *result = NULL;
5637 static bool non_empty_object;
5638 static bool schemaquoted;
5639 static bool objectquoted;
5640
5641 /*
5642 * If this is the first time for this completion, we fetch a list of our
5643 * "things" from the backend.
5644 */
5645 if (state == 0)
5646 {
5647 PQExpBufferData query_buffer;
5648 char *schemaname;
5649 char *objectname;
5650 char *e_object_like;
5651 char *e_schemaname;
5652 char *e_ref_object;
5653 char *e_ref_schema;
5654
5655 /* Reset static state, ensuring no memory leaks */
5656 list_index = 0;
5657 num_schema_only = 0;
5658 num_query_other = 0;
5659 num_keywords = 0;
5660 PQclear(result);
5661 result = NULL;
5662
5663 /* Parse text, splitting into schema and object name if needed */
5664 if (verbatim)
5665 {
5666 objectname = pg_strdup(text);
5667 schemaname = NULL;
5668 }
5669 else
5670 {
5671 parse_identifier(text,
5672 &schemaname, &objectname,
5673 &schemaquoted, &objectquoted);
5674 }
5675
5676 /* Remember whether the user has typed anything in the object part */
5677 non_empty_object = (*objectname != '\0');
5678
5679 /*
5680 * Convert objectname to a LIKE prefix pattern (e.g. 'foo%'), and set
5681 * up suitably-escaped copies of all the strings we need.
5682 */
5683 e_object_like = make_like_pattern(objectname);
5684
5685 if (schemaname)
5686 e_schemaname = escape_string(schemaname);
5687 else
5688 e_schemaname = NULL;
5689
5690 if (completion_ref_object)
5691 e_ref_object = escape_string(completion_ref_object);
5692 else
5693 e_ref_object = NULL;
5694
5695 if (completion_ref_schema)
5696 e_ref_schema = escape_string(completion_ref_schema);
5697 else
5698 e_ref_schema = NULL;
5699
5700 initPQExpBuffer(&query_buffer);
5701
5702 if (schema_query)
5703 {
5704 Assert(simple_query == NULL);
5705
5706 /*
5707 * We issue different queries depending on whether the input is
5708 * already qualified or not. schema_query gives us the pieces to
5709 * assemble.
5710 */
5711 if (schemaname == NULL || schema_query->namespace == NULL)
5712 {
5713 /* Get unqualified names matching the input-so-far */
5714 appendPQExpBufferStr(&query_buffer, "SELECT ");
5715 if (schema_query->use_distinct)
5716 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
5717 appendPQExpBuffer(&query_buffer,
5718 "%s, NULL::pg_catalog.text FROM %s",
5719 schema_query->result,
5720 schema_query->catname);
5721 if (schema_query->refnamespace && completion_ref_schema)
5722 appendPQExpBufferStr(&query_buffer,
5723 ", pg_catalog.pg_namespace nr");
5724 appendPQExpBufferStr(&query_buffer, " WHERE ");
5725 if (schema_query->selcondition)
5726 appendPQExpBuffer(&query_buffer, "%s AND ",
5727 schema_query->selcondition);
5728 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s'",
5729 schema_query->result,
5730 e_object_like);
5731 if (schema_query->viscondition)
5732 appendPQExpBuffer(&query_buffer, " AND %s",
5733 schema_query->viscondition);
5734 if (schema_query->refname)
5735 {
5736 Assert(completion_ref_object);
5737 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
5738 schema_query->refname, e_ref_object);
5739 if (schema_query->refnamespace && completion_ref_schema)
5740 appendPQExpBuffer(&query_buffer,
5741 " AND %s = nr.oid AND nr.nspname = '%s'",
5742 schema_query->refnamespace,
5743 e_ref_schema);
5744 else if (schema_query->refviscondition)
5745 appendPQExpBuffer(&query_buffer,
5746 " AND %s",
5747 schema_query->refviscondition);
5748 }
5749
5750 /*
5751 * When fetching relation names, suppress system catalogs
5752 * unless the input-so-far begins with "pg_". This is a
5753 * compromise between not offering system catalogs for
5754 * completion at all, and having them swamp the result when
5755 * the input is just "p".
5756 */
5757 if (strcmp(schema_query->catname,
5758 "pg_catalog.pg_class c") == 0 &&
5759 strncmp(objectname, "pg_", 3) != 0)
5760 {
5761 appendPQExpBufferStr(&query_buffer,
5762 " AND c.relnamespace <> (SELECT oid FROM"
5763 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
5764 }
5765
5766 /*
5767 * If the target object type can be schema-qualified, add in
5768 * schema names matching the input-so-far.
5769 */
5770 if (schema_query->namespace)
5771 {
5772 appendPQExpBuffer(&query_buffer, "\nUNION ALL\n"
5773 "SELECT NULL::pg_catalog.text, n.nspname "
5774 "FROM pg_catalog.pg_namespace n "
5775 "WHERE n.nspname LIKE '%s'",
5776 e_object_like);
5777
5778 /*
5779 * Likewise, suppress system schemas unless the
5780 * input-so-far begins with "pg_".
5781 */
5782 if (strncmp(objectname, "pg_", 3) != 0)
5783 appendPQExpBufferStr(&query_buffer,
5784 " AND n.nspname NOT LIKE E'pg\\\\_%'");
5785
5786 /*
5787 * Since we're matching these schema names to the object
5788 * name, handle their quoting using the object name's
5789 * quoting state.
5790 */
5791 schemaquoted = objectquoted;
5792 }
5793 }
5794 else
5795 {
5796 /* Input is qualified, so produce only qualified names */
5797 appendPQExpBufferStr(&query_buffer, "SELECT ");
5798 if (schema_query->use_distinct)
5799 appendPQExpBufferStr(&query_buffer, "DISTINCT ");
5800 appendPQExpBuffer(&query_buffer, "%s, n.nspname "
5801 "FROM %s, pg_catalog.pg_namespace n",
5802 schema_query->result,
5803 schema_query->catname);
5804 if (schema_query->refnamespace && completion_ref_schema)
5805 appendPQExpBufferStr(&query_buffer,
5806 ", pg_catalog.pg_namespace nr");
5807 appendPQExpBuffer(&query_buffer, " WHERE %s = n.oid AND ",
5808 schema_query->namespace);
5809 if (schema_query->selcondition)
5810 appendPQExpBuffer(&query_buffer, "%s AND ",
5811 schema_query->selcondition);
5812 appendPQExpBuffer(&query_buffer, "(%s) LIKE '%s' AND ",
5813 schema_query->result,
5814 e_object_like);
5815 appendPQExpBuffer(&query_buffer, "n.nspname = '%s'",
5816 e_schemaname);
5817 if (schema_query->refname)
5818 {
5819 Assert(completion_ref_object);
5820 appendPQExpBuffer(&query_buffer, " AND %s = '%s'",
5821 schema_query->refname, e_ref_object);
5822 if (schema_query->refnamespace && completion_ref_schema)
5823 appendPQExpBuffer(&query_buffer,
5824 " AND %s = nr.oid AND nr.nspname = '%s'",
5825 schema_query->refnamespace,
5826 e_ref_schema);
5827 else if (schema_query->refviscondition)
5828 appendPQExpBuffer(&query_buffer,
5829 " AND %s",
5830 schema_query->refviscondition);
5831 }
5832 }
5833 }
5834 else
5835 {
5836 Assert(simple_query);
5837 /* simple_query is an sprintf-style format string */
5838 appendPQExpBuffer(&query_buffer, simple_query,
5839 e_object_like,
5840 e_ref_object, e_ref_schema);
5841 }
5842
5843 /* Limit the number of records in the result */
5844 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
5845 completion_max_records);
5846
5847 /* Finally, we can issue the query */
5848 result = exec_query(query_buffer.data);
5849
5850 /* Clean up */
5851 termPQExpBuffer(&query_buffer);
5852 free(schemaname);
5853 free(objectname);
5854 free(e_object_like);
5855 free(e_schemaname);
5856 free(e_ref_object);
5857 free(e_ref_schema);
5858 }
5859
5860 /* Return the next result, if any, but not if the query failed */
5861 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
5862 {
5863 int nskip;
5864
5865 while (list_index < PQntuples(result))
5866 {
5867 const char *item = NULL;
5868 const char *nsp = NULL;
5869
5870 if (!PQgetisnull(result, list_index, 0))
5871 item = PQgetvalue(result, list_index, 0);
5872 if (PQnfields(result) > 1 &&
5873 !PQgetisnull(result, list_index, 1))
5874 nsp = PQgetvalue(result, list_index, 1);
5875 list_index++;
5876
5877 /* In verbatim mode, we return all the items as-is */
5878 if (verbatim)
5879 {
5880 num_query_other++;
5881 return pg_strdup(item);
5882 }
5883
5884 /*
5885 * In normal mode, a name requiring quoting will be returned only
5886 * if the input was empty or quoted. Otherwise the user might see
5887 * completion inserting a quote she didn't type, which is
5888 * surprising. This restriction also dodges some odd behaviors of
5889 * some versions of readline/libedit.
5890 */
5891 if (non_empty_object)
5892 {
5893 if (item && !objectquoted && identifier_needs_quotes(item))
5894 continue;
5895 if (nsp && !schemaquoted && identifier_needs_quotes(nsp))
5896 continue;
5897 }
5898
5899 /* Count schema-only results for hack below */
5900 if (item == NULL && nsp != NULL)
5901 num_schema_only++;
5902 else
5903 num_query_other++;
5904
5905 return requote_identifier(nsp, item, schemaquoted, objectquoted);
5906 }
5907
5908 /*
5909 * When the query result is exhausted, check for hard-wired keywords.
5910 * These will only be returned if they match the input-so-far,
5911 * ignoring case.
5912 */
5913 nskip = list_index - PQntuples(result);
5914 if (schema_query && schema_query->keywords)
5915 {
5916 const char *const *itemp = schema_query->keywords;
5917
5918 while (*itemp)
5919 {
5920 const char *item = *itemp++;
5921
5922 if (nskip-- > 0)
5923 continue;
5924 list_index++;
5925 if (pg_strncasecmp(text, item, strlen(text)) == 0)
5926 {
5927 num_keywords++;
5928 return pg_strdup_keyword_case(item, text);
5929 }
5930 }
5931 }
5932 if (keywords)
5933 {
5934 const char *const *itemp = keywords;
5935
5936 while (*itemp)
5937 {
5938 const char *item = *itemp++;
5939
5940 if (nskip-- > 0)
5941 continue;
5942 list_index++;
5943 if (pg_strncasecmp(text, item, strlen(text)) == 0)
5944 {
5945 num_keywords++;
5946 return pg_strdup_keyword_case(item, text);
5947 }
5948 }
5949 }
5950 }
5951
5952 /*
5953 * Hack: if we returned only bare schema names, don't let Readline add a
5954 * space afterwards. Otherwise the schema will stop being part of the
5955 * completion subject text, which is not what we want.
5956 */
5957 if (num_schema_only > 0 && num_query_other == 0 && num_keywords == 0)
5958 rl_completion_append_character = '\0';
5959
5960 /* No more matches, so free the result structure and return null */
5961 PQclear(result);
5962 result = NULL;
5963 return NULL;
5964}
5965
5966
5967/*
5968 * Set up completion_ref_object and completion_ref_schema
5969 * by parsing the given word. These variables can then be
5970 * used in a query passed to _complete_from_query.
5971 */
5972static void
5973set_completion_reference(const char *word)
5974{
5975 bool schemaquoted,
5976 objectquoted;
5977
5978 parse_identifier(word,
5979 &completion_ref_schema, &completion_ref_object,
5980 &schemaquoted, &objectquoted);
5981}
5982
5983/*
5984 * Set up completion_ref_object when it should just be
5985 * the given word verbatim.
5986 */
5987static void
5988set_completion_reference_verbatim(const char *word)
5989{
5990 completion_ref_schema = NULL;
5991 completion_ref_object = pg_strdup(word);
5992}
5993
5994
5995/*
5996 * This function returns in order one of a fixed, NULL pointer terminated list
5997 * of strings (if matching). This can be used if there are only a fixed number
5998 * SQL words that can appear at certain spot.
5999 */
6000static char *
6001complete_from_list(const char *text, int state)
6002{
6003 static int string_length,
6004 list_index,
6005 matches;
6006 static bool casesensitive;
6007 const char *item;
6008
6009 /* need to have a list */
6010 Assert(completion_charpp != NULL);
6011
6012 /* Initialization */
6013 if (state == 0)
6014 {
6015 list_index = 0;
6016 string_length = strlen(text);
6017 casesensitive = completion_case_sensitive;
6018 matches = 0;
6019 }
6020
6021 while ((item = completion_charpp[list_index++]))
6022 {
6023 /* First pass is case sensitive */
6024 if (casesensitive && strncmp(text, item, string_length) == 0)
6025 {
6026 matches++;
6027 return pg_strdup(item);
6028 }
6029
6030 /* Second pass is case insensitive, don't bother counting matches */
6031 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
6032 {
6033 if (completion_case_sensitive)
6034 return pg_strdup(item);
6035 else
6036
6037 /*
6038 * If case insensitive matching was requested initially,
6039 * adjust the case according to setting.
6040 */
6041 return pg_strdup_keyword_case(item, text);
6042 }
6043 }
6044
6045 /*
6046 * No matches found. If we're not case insensitive already, lets switch to
6047 * being case insensitive and try again
6048 */
6049 if (casesensitive && matches == 0)
6050 {
6051 casesensitive = false;
6052 list_index = 0;
6053 state++;
6054 return complete_from_list(text, state);
6055 }
6056
6057 /* If no more matches, return null. */
6058 return NULL;
6059}
6060
6061
6062/*
6063 * This function returns one fixed string the first time even if it doesn't
6064 * match what's there, and nothing the second time. The string
6065 * to be used must be in completion_charp.
6066 *
6067 * If the given string is "", this has the effect of preventing readline
6068 * from doing any completion. (Without this, readline tries to do filename
6069 * completion which is seldom the right thing.)
6070 *
6071 * If the given string is not empty, readline will replace whatever the
6072 * user typed with that string. This behavior might be useful if it's
6073 * completely certain that we know what must appear at a certain spot,
6074 * so that it's okay to overwrite misspellings. In practice, given the
6075 * relatively lame parsing technology used in this file, the level of
6076 * certainty is seldom that high, so that you probably don't want to
6077 * use this. Use complete_from_list with a one-element list instead;
6078 * that won't try to auto-correct "misspellings".
6079 */
6080static char *
6081complete_from_const(const char *text, int state)
6082{
6083 Assert(completion_charp != NULL);
6084 if (state == 0)
6085 {
6086 if (completion_case_sensitive)
6087 return pg_strdup(completion_charp);
6088 else
6089
6090 /*
6091 * If case insensitive matching was requested initially, adjust
6092 * the case according to setting.
6093 */
6094 return pg_strdup_keyword_case(completion_charp, text);
6095 }
6096 else
6097 return NULL;
6098}
6099
6100
6101/*
6102 * This function appends the variable name with prefix and suffix to
6103 * the variable names array.
6104 */
6105static void
6106append_variable_names(char ***varnames, int *nvars,
6107 int *maxvars, const char *varname,
6108 const char *prefix, const char *suffix)
6109{
6110 if (*nvars >= *maxvars)
6111 {
6112 *maxvars *= 2;
6113 *varnames = (char **) pg_realloc(*varnames,
6114 ((*maxvars) + 1) * sizeof(char *));
6115 }
6116
6117 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
6118}
6119
6120
6121/*
6122 * This function supports completion with the name of a psql variable.
6123 * The variable names can be prefixed and suffixed with additional text
6124 * to support quoting usages. If need_value is true, only variables
6125 * that are currently set are included; otherwise, special variables
6126 * (those that have hooks) are included even if currently unset.
6127 */
6128static char **
6129complete_from_variables(const char *text, const char *prefix, const char *suffix,
6130 bool need_value)
6131{
6132 char **matches;
6133 char **varnames;
6134 int nvars = 0;
6135 int maxvars = 100;
6136 int i;
6137 struct _variable *ptr;
6138
6139 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
6140
6141 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
6142 {
6143 if (need_value && !(ptr->value))
6144 continue;
6145 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
6146 prefix, suffix);
6147 }
6148
6149 varnames[nvars] = NULL;
6150 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
6151
6152 for (i = 0; i < nvars; i++)
6153 free(varnames[i]);
6154 free(varnames);
6155
6156 return matches;
6157}
6158
6159
6160/*
6161 * This function wraps rl_filename_completion_function() to strip quotes from
6162 * the input before searching for matches and to quote any matches for which
6163 * the consuming command will require it.
6164 *
6165 * Caller must set completion_charp to a zero- or one-character string
6166 * containing the escape character. This is necessary since \copy has no
6167 * escape character, but every other backslash command recognizes "\" as an
6168 * escape character.
6169 *
6170 * Caller must also set completion_force_quote to indicate whether to force
6171 * quotes around the result. (The SQL COPY command requires that.)
6172 */
6173static char *
6174complete_from_files(const char *text, int state)
6175{
6176#ifdef USE_FILENAME_QUOTING_FUNCTIONS
6177
6178 /*
6179 * If we're using a version of Readline that supports filename quoting
6180 * hooks, rely on those, and invoke rl_filename_completion_function()
6181 * without messing with its arguments. Readline does stuff internally
6182 * that does not work well at all if we try to handle dequoting here.
6183 * Instead, Readline will call quote_file_name() and dequote_file_name()
6184 * (see below) at appropriate times.
6185 *
6186 * ... or at least, mostly it will. There are some paths involving
6187 * unmatched file names in which Readline never calls quote_file_name(),
6188 * and if left to its own devices it will incorrectly append a quote
6189 * anyway. Set rl_completion_suppress_quote to prevent that. If we do
6190 * get to quote_file_name(), we'll clear this again. (Yes, this seems
6191 * like it's working around Readline bugs.)
6192 */
6193#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
6194 rl_completion_suppress_quote = 1;
6195#endif
6196
6197 /* If user typed a quote, force quoting (never remove user's quote) */
6198 if (*text == '\'')
6199 completion_force_quote = true;
6200
6201 return rl_filename_completion_function(text, state);
6202#else
6203
6204 /*
6205 * Otherwise, we have to do the best we can.
6206 */
6207 static const char *unquoted_text;
6208 char *unquoted_match;
6209 char *ret = NULL;
6210
6211 /* If user typed a quote, force quoting (never remove user's quote) */
6212 if (*text == '\'')
6213 completion_force_quote = true;
6214
6215 if (state == 0)
6216 {
6217 /* Initialization: stash the unquoted input. */
6218 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
6219 false, true, pset.encoding);
6220 /* expect a NULL return for the empty string only */
6221 if (!unquoted_text)
6222 {
6223 Assert(*text == '\0');
6224 unquoted_text = text;
6225 }
6226 }
6227
6228 unquoted_match = rl_filename_completion_function(unquoted_text, state);
6229 if (unquoted_match)
6230 {
6231 struct stat statbuf;
6232 bool is_dir = (stat(unquoted_match, &statbuf) == 0 &&
6233 S_ISDIR(statbuf.st_mode) != 0);
6234
6235 /* Re-quote the result, if needed. */
6236 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
6237 '\'', *completion_charp,
6238 completion_force_quote,
6239 pset.encoding);
6240 if (ret)
6241 free(unquoted_match);
6242 else
6243 ret = unquoted_match;
6244
6245 /*
6246 * If it's a directory, replace trailing quote with a slash; this is
6247 * usually more convenient. (If we didn't quote, leave this to
6248 * libedit.)
6249 */
6250 if (*ret == '\'' && is_dir)
6251 {
6252 char *retend = ret + strlen(ret) - 1;
6253
6254 Assert(*retend == '\'');
6255 *retend = '/';
6256 /* Prevent libedit from adding a space, too */
6257 rl_completion_append_character = '\0';
6258 }
6259 }
6260
6261 return ret;
6262#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
6263}
6264
6265
6266/* HELPER FUNCTIONS */
6267
6268
6269/*
6270 * Make a pg_strdup copy of s and convert the case according to
6271 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
6272 */
6273static char *
6274pg_strdup_keyword_case(const char *s, const char *ref)
6275{
6276 char *ret,
6277 *p;
6278 unsigned char first = ref[0];
6279
6280 ret = pg_strdup(s);
6281
6284 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
6285 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
6286 {
6287 for (p = ret; *p; p++)
6288 *p = pg_tolower((unsigned char) *p);
6289 }
6290 else
6291 {
6292 for (p = ret; *p; p++)
6293 *p = pg_toupper((unsigned char) *p);
6294 }
6295
6296 return ret;
6297}
6298
6299
6300/*
6301 * escape_string - Escape argument for use as string literal.
6302 *
6303 * The returned value has to be freed.
6304 */
6305static char *
6306escape_string(const char *text)
6307{
6308 size_t text_length;
6309 char *result;
6310
6311 text_length = strlen(text);
6312
6313 result = pg_malloc(text_length * 2 + 1);
6314 PQescapeStringConn(pset.db, result, text, text_length, NULL);
6315
6316 return result;
6317}
6318
6319
6320/*
6321 * make_like_pattern - Convert argument to a LIKE prefix pattern.
6322 *
6323 * We escape _ and % in the given text by backslashing, append a % to
6324 * represent "any subsequent characters", and then pass the string through
6325 * escape_string() so it's ready to insert in a query. The result needs
6326 * to be freed.
6327 */
6328static char *
6329make_like_pattern(const char *word)
6330{
6331 char *result;
6332 char *buffer = pg_malloc(strlen(word) * 2 + 2);
6333 char *bptr = buffer;
6334
6335 while (*word)
6336 {
6337 if (*word == '_' || *word == '%')
6338 *bptr++ = '\\';
6339 if (IS_HIGHBIT_SET(*word))
6340 {
6341 /*
6342 * Transfer multibyte characters without further processing, to
6343 * avoid getting confused in unsafe client encodings.
6344 */
6345 int chlen = PQmblenBounded(word, pset.encoding);
6346
6347 while (chlen-- > 0)
6348 *bptr++ = *word++;
6349 }
6350 else
6351 *bptr++ = *word++;
6352 }
6353 *bptr++ = '%';
6354 *bptr = '\0';
6355
6356 result = escape_string(buffer);
6357 free(buffer);
6358 return result;
6359}
6360
6361
6362/*
6363 * parse_identifier - Parse a possibly-schema-qualified SQL identifier.
6364 *
6365 * This involves splitting off the schema name if present, de-quoting,
6366 * and downcasing any unquoted text. We are a bit laxer than the backend
6367 * in that we allow just portions of a name to be quoted --- that's because
6368 * psql metacommands have traditionally behaved that way.
6369 *
6370 * Outputs are a malloc'd schema name (NULL if none), malloc'd object name,
6371 * and booleans telling whether any part of the schema and object name was
6372 * double-quoted.
6373 */
6374static void
6375parse_identifier(const char *ident,
6376 char **schemaname, char **objectname,
6377 bool *schemaquoted, bool *objectquoted)
6378{
6379 size_t buflen = strlen(ident) + 1;
6380 bool enc_is_single_byte = (pg_encoding_max_length(pset.encoding) == 1);
6381 char *sname;
6382 char *oname;
6383 char *optr;
6384 bool inquotes;
6385
6386 /* Initialize, making a certainly-large-enough output buffer */
6387 sname = NULL;
6388 oname = pg_malloc(buflen);
6389 *schemaquoted = *objectquoted = false;
6390 /* Scan */
6391 optr = oname;
6392 inquotes = false;
6393 while (*ident)
6394 {
6395 unsigned char ch = (unsigned char) *ident++;
6396
6397 if (ch == '"')
6398 {
6399 if (inquotes && *ident == '"')
6400 {
6401 /* two quote marks within a quoted identifier = emit quote */
6402 *optr++ = '"';
6403 ident++;
6404 }
6405 else
6406 {
6407 inquotes = !inquotes;
6408 *objectquoted = true;
6409 }
6410 }
6411 else if (ch == '.' && !inquotes)
6412 {
6413 /* Found a schema name, transfer it to sname / *schemaquoted */
6414 *optr = '\0';
6415 free(sname); /* drop any catalog name */
6416 sname = oname;
6417 oname = pg_malloc(buflen);
6418 optr = oname;
6419 *schemaquoted = *objectquoted;
6420 *objectquoted = false;
6421 }
6422 else if (!enc_is_single_byte && IS_HIGHBIT_SET(ch))
6423 {
6424 /*
6425 * Transfer multibyte characters without further processing. They
6426 * wouldn't be affected by our downcasing rule anyway, and this
6427 * avoids possibly doing the wrong thing in unsafe client
6428 * encodings.
6429 */
6430 int chlen = PQmblenBounded(ident - 1, pset.encoding);
6431
6432 *optr++ = (char) ch;
6433 while (--chlen > 0)
6434 *optr++ = *ident++;
6435 }
6436 else
6437 {
6438 if (!inquotes)
6439 {
6440 /*
6441 * This downcasing transformation should match the backend's
6442 * downcase_identifier() as best we can. We do not know the
6443 * backend's locale, though, so it's necessarily approximate.
6444 * We assume that psql is operating in the same locale and
6445 * encoding as the backend.
6446 */
6447 if (ch >= 'A' && ch <= 'Z')
6448 ch += 'a' - 'A';
6449 else if (enc_is_single_byte && IS_HIGHBIT_SET(ch) && isupper(ch))
6450 ch = tolower(ch);
6451 }
6452 *optr++ = (char) ch;
6453 }
6454 }
6455
6456 *optr = '\0';
6457 *schemaname = sname;
6458 *objectname = oname;
6459}
6460
6461
6462/*
6463 * requote_identifier - Reconstruct a possibly-schema-qualified SQL identifier.
6464 *
6465 * Build a malloc'd string containing the identifier, with quoting applied
6466 * as necessary. This is more or less the inverse of parse_identifier;
6467 * in particular, if an input component was quoted, we'll quote the output
6468 * even when that isn't strictly required.
6469 *
6470 * Unlike parse_identifier, we handle the case where a schema and no
6471 * object name is provided, producing just "schema.".
6472 */
6473static char *
6474requote_identifier(const char *schemaname, const char *objectname,
6475 bool quote_schema, bool quote_object)
6476{
6477 char *result;
6478 size_t buflen = 1; /* count the trailing \0 */
6479 char *ptr;
6480
6481 /*
6482 * We could use PQescapeIdentifier for some of this, but not all, and it
6483 * adds more notational cruft than it seems worth.
6484 */
6485 if (schemaname)
6486 {
6487 buflen += strlen(schemaname) + 1; /* +1 for the dot */
6488 if (!quote_schema)
6489 quote_schema = identifier_needs_quotes(schemaname);
6490 if (quote_schema)
6491 {
6492 buflen += 2; /* account for quote marks */
6493 for (const char *p = schemaname; *p; p++)
6494 {
6495 if (*p == '"')
6496 buflen++;
6497 }
6498 }
6499 }
6500 if (objectname)
6501 {
6502 buflen += strlen(objectname);
6503 if (!quote_object)
6504 quote_object = identifier_needs_quotes(objectname);
6505 if (quote_object)
6506 {
6507 buflen += 2; /* account for quote marks */
6508 for (const char *p = objectname; *p; p++)
6509 {
6510 if (*p == '"')
6511 buflen++;
6512 }
6513 }
6514 }
6515 result = pg_malloc(buflen);
6516 ptr = result;
6517 if (schemaname)
6518 {
6519 if (quote_schema)
6520 *ptr++ = '"';
6521 for (const char *p = schemaname; *p; p++)
6522 {
6523 *ptr++ = *p;
6524 if (*p == '"')
6525 *ptr++ = '"';
6526 }
6527 if (quote_schema)
6528 *ptr++ = '"';
6529 *ptr++ = '.';
6530 }
6531 if (objectname)
6532 {
6533 if (quote_object)
6534 *ptr++ = '"';
6535 for (const char *p = objectname; *p; p++)
6536 {
6537 *ptr++ = *p;
6538 if (*p == '"')
6539 *ptr++ = '"';
6540 }
6541 if (quote_object)
6542 *ptr++ = '"';
6543 }
6544 *ptr = '\0';
6545 return result;
6546}
6547
6548
6549/*
6550 * Detect whether an identifier must be double-quoted.
6551 *
6552 * Note we'll quote anything that's not ASCII; the backend's quote_ident()
6553 * does the same. Perhaps this could be relaxed in future.
6554 */
6555static bool
6556identifier_needs_quotes(const char *ident)
6557{
6558 int kwnum;
6559
6560 /* Check syntax. */
6561 if (!((ident[0] >= 'a' && ident[0] <= 'z') || ident[0] == '_'))
6562 return true;
6563 if (strspn(ident, "abcdefghijklmnopqrstuvwxyz0123456789_$") != strlen(ident))
6564 return true;
6565
6566 /*
6567 * Check for keyword. We quote keywords except for unreserved ones.
6568 *
6569 * It is possible that our keyword list doesn't quite agree with the
6570 * server's, but this should be close enough for tab-completion purposes.
6571 *
6572 * Note: ScanKeywordLookup() does case-insensitive comparison, but that's
6573 * fine, since we already know we have all-lower-case.
6574 */
6576
6577 if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD)
6578 return true;
6579
6580 return false;
6581}
6582
6583
6584/*
6585 * Execute a query, returning NULL if there was any error.
6586 * This should be the preferred way of talking to the database in this file.
6587 */
6588static PGresult *
6589exec_query(const char *query)
6590{
6591 PGresult *result;
6592
6593 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
6594 return NULL;
6595
6596 result = PQexec(pset.db, query);
6597
6598 if (PQresultStatus(result) != PGRES_TUPLES_OK)
6599 {
6600 /*
6601 * Printing an error while the user is typing would be quite annoying,
6602 * so we don't. This does complicate debugging of this code; but you
6603 * can look in the server log instead.
6604 */
6605#ifdef NOT_USED
6606 pg_log_error("tab completion query failed: %s\nQuery was:\n%s",
6607 PQerrorMessage(pset.db), query);
6608#endif
6609 PQclear(result);
6610 result = NULL;
6611 }
6612
6613 return result;
6614}
6615
6616
6617/*
6618 * Parse all the word(s) before point.
6619 *
6620 * Returns a malloc'd array of character pointers that point into the malloc'd
6621 * data array returned to *buffer; caller must free() both of these when done.
6622 * *nwords receives the number of words found, ie, the valid length of the
6623 * return array.
6624 *
6625 * Words are returned right to left, that is, previous_words[0] gets the last
6626 * word before point, previous_words[1] the next-to-last, etc.
6627 */
6628static char **
6629get_previous_words(int point, char **buffer, int *nwords)
6630{
6631 char **previous_words;
6632 char *buf;
6633 char *outptr;
6634 int words_found = 0;
6635 int i;
6636
6637 /*
6638 * If we have anything in tab_completion_query_buf, paste it together with
6639 * rl_line_buffer to construct the full query. Otherwise we can just use
6640 * rl_line_buffer as the input string.
6641 */
6643 {
6645 buf = pg_malloc(point + i + 2);
6647 buf[i++] = '\n';
6648 memcpy(buf + i, rl_line_buffer, point);
6649 i += point;
6650 buf[i] = '\0';
6651 /* Readjust point to reference appropriate offset in buf */
6652 point = i;
6653 }
6654 else
6655 buf = rl_line_buffer;
6656
6657 /*
6658 * Allocate an array of string pointers and a buffer to hold the strings
6659 * themselves. The worst case is that the line contains only
6660 * non-whitespace WORD_BREAKS characters, making each one a separate word.
6661 * This is usually much more space than we need, but it's cheaper than
6662 * doing a separate malloc() for each word.
6663 */
6664 previous_words = (char **) pg_malloc(point * sizeof(char *));
6665 *buffer = outptr = (char *) pg_malloc(point * 2);
6666
6667 /*
6668 * First we look for a non-word char before the current point. (This is
6669 * probably useless, if readline is on the same page as we are about what
6670 * is a word, but if so it's cheap.)
6671 */
6672 for (i = point - 1; i >= 0; i--)
6673 {
6674 if (strchr(WORD_BREAKS, buf[i]))
6675 break;
6676 }
6677 point = i;
6678
6679 /*
6680 * Now parse words, working backwards, until we hit start of line. The
6681 * backwards scan has some interesting but intentional properties
6682 * concerning parenthesis handling.
6683 */
6684 while (point >= 0)
6685 {
6686 int start,
6687 end;
6688 bool inquotes = false;
6689 int parentheses = 0;
6690
6691 /* now find the first non-space which then constitutes the end */
6692 end = -1;
6693 for (i = point; i >= 0; i--)
6694 {
6695 if (!isspace((unsigned char) buf[i]))
6696 {
6697 end = i;
6698 break;
6699 }
6700 }
6701 /* if no end found, we're done */
6702 if (end < 0)
6703 break;
6704
6705 /*
6706 * Otherwise we now look for the start. The start is either the last
6707 * character before any word-break character going backwards from the
6708 * end, or it's simply character 0. We also handle open quotes and
6709 * parentheses.
6710 */
6711 for (start = end; start > 0; start--)
6712 {
6713 if (buf[start] == '"')
6714 inquotes = !inquotes;
6715 if (!inquotes)
6716 {
6717 if (buf[start] == ')')
6718 parentheses++;
6719 else if (buf[start] == '(')
6720 {
6721 if (--parentheses <= 0)
6722 break;
6723 }
6724 else if (parentheses == 0 &&
6725 strchr(WORD_BREAKS, buf[start - 1]))
6726 break;
6727 }
6728 }
6729
6730 /* Return the word located at start to end inclusive */
6731 previous_words[words_found++] = outptr;
6732 i = end - start + 1;
6733 memcpy(outptr, &buf[start], i);
6734 outptr += i;
6735 *outptr++ = '\0';
6736
6737 /* Continue searching */
6738 point = start - 1;
6739 }
6740
6741 /* Release parsing input workspace, if we made one above */
6742 if (buf != rl_line_buffer)
6743 free(buf);
6744
6745 *nwords = words_found;
6746 return previous_words;
6747}
6748
6749/*
6750 * Look up the type for the GUC variable with the passed name.
6751 *
6752 * Returns NULL if the variable is unknown. Otherwise the returned string,
6753 * containing the type, has to be freed.
6754 */
6755static char *
6756get_guctype(const char *varname)
6757{
6758 PQExpBufferData query_buffer;
6759 char *e_varname;
6760 PGresult *result;
6761 char *guctype = NULL;
6762
6763 e_varname = escape_string(varname);
6764
6765 initPQExpBuffer(&query_buffer);
6766 appendPQExpBuffer(&query_buffer,
6767 "SELECT vartype FROM pg_catalog.pg_settings "
6768 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
6769 e_varname);
6770
6771 result = exec_query(query_buffer.data);
6772 termPQExpBuffer(&query_buffer);
6773 free(e_varname);
6774
6775 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
6776 guctype = pg_strdup(PQgetvalue(result, 0, 0));
6777
6778 PQclear(result);
6779
6780 return guctype;
6781}
6782
6783#ifdef USE_FILENAME_QUOTING_FUNCTIONS
6784
6785/*
6786 * Quote a filename according to SQL rules, returning a malloc'd string.
6787 * completion_charp must point to escape character or '\0', and
6788 * completion_force_quote must be set correctly, as per comments for
6789 * complete_from_files().
6790 */
6791static char *
6792quote_file_name(char *fname, int match_type, char *quote_pointer)
6793{
6794 char *s;
6795 struct stat statbuf;
6796
6797 /* Quote if needed. */
6798 s = quote_if_needed(fname, " \t\r\n\"`",
6799 '\'', *completion_charp,
6800 completion_force_quote,
6801 pset.encoding);
6802 if (!s)
6803 s = pg_strdup(fname);
6804
6805 /*
6806 * However, some of the time we have to strip the trailing quote from what
6807 * we send back. Never strip the trailing quote if the user already typed
6808 * one; otherwise, suppress the trailing quote if we have multiple/no
6809 * matches (because we don't want to add a quote if the input is seemingly
6810 * unfinished), or if the input was already quoted (because Readline will
6811 * do arguably-buggy things otherwise), or if the file does not exist, or
6812 * if it's a directory.
6813 */
6814 if (*s == '\'' &&
6815 completion_last_char != '\'' &&
6816 (match_type != SINGLE_MATCH ||
6817 (quote_pointer && *quote_pointer == '\'') ||
6818 stat(fname, &statbuf) != 0 ||
6819 S_ISDIR(statbuf.st_mode)))
6820 {
6821 char *send = s + strlen(s) - 1;
6822
6823 Assert(*send == '\'');
6824 *send = '\0';
6825 }
6826
6827 /*
6828 * And now we can let Readline do its thing with possibly adding a quote
6829 * on its own accord. (This covers some additional cases beyond those
6830 * dealt with above.)
6831 */
6832#ifdef HAVE_RL_COMPLETION_SUPPRESS_QUOTE
6833 rl_completion_suppress_quote = 0;
6834#endif
6835
6836 /*
6837 * If user typed a leading quote character other than single quote (i.e.,
6838 * double quote), zap it, so that we replace it with the correct single
6839 * quote.
6840 */
6841 if (quote_pointer && *quote_pointer != '\'')
6842 *quote_pointer = '\0';
6843
6844 return s;
6845}
6846
6847/*
6848 * Dequote a filename, if it's quoted.
6849 * completion_charp must point to escape character or '\0', as per
6850 * comments for complete_from_files().
6851 */
6852static char *
6853dequote_file_name(char *fname, int quote_char)
6854{
6855 char *unquoted_fname;
6856
6857 /*
6858 * If quote_char is set, it's not included in "fname". We have to add it
6859 * or strtokx will not interpret the string correctly (notably, it won't
6860 * recognize escapes).
6861 */
6862 if (quote_char == '\'')
6863 {
6864 char *workspace = (char *) pg_malloc(strlen(fname) + 2);
6865
6866 workspace[0] = quote_char;
6867 strcpy(workspace + 1, fname);
6868 unquoted_fname = strtokx(workspace, "", NULL, "'", *completion_charp,
6869 false, true, pset.encoding);
6870 free(workspace);
6871 }
6872 else
6873 unquoted_fname = strtokx(fname, "", NULL, "'", *completion_charp,
6874 false, true, pset.encoding);
6875
6876 /* expect a NULL return for the empty string only */
6877 if (!unquoted_fname)
6878 {
6879 Assert(*fname == '\0');
6880 unquoted_fname = fname;
6881 }
6882
6883 /* readline expects a malloc'd result that it is to free */
6884 return pg_strdup(unquoted_fname);
6885}
6886
6887#endif /* USE_FILENAME_QUOTING_FUNCTIONS */
6888
6889#endif /* USE_READLINE */
bool recognized_connection_string(const char *connstr)
Definition: common.c:2625
struct varlena text
Definition: c.h:671
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1126
uint32 bits32
Definition: c.h:511
#define CppAsString2(x)
Definition: c.h:363
#define lengthof(array)
Definition: c.h:759
const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]
Definition: keywords.c:29
ConnStatusType PQstatus(const PGconn *conn)
Definition: fe-connect.c:7490
char * PQerrorMessage(const PGconn *conn)
Definition: fe-connect.c:7553
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
void PQclear(PGresult *res)
Definition: fe-exec.c:721
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
Assert(PointerIsAligned(start, uint64))
return str start
#define free(a)
Definition: header.h:65
#define ident
Definition: indent_codes.h:47
int i
Definition: isn.c:77
static const JsonPathKeyword keywords[]
PGDLLIMPORT const ScanKeywordList ScanKeywords
#define UNRESERVED_KEYWORD
Definition: keywords.h:20
int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)
Definition: kwlookup.c:38
@ CONNECTION_OK
Definition: libpq-fe.h:84
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:128
#define pg_log_error(...)
Definition: logging.h:106
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1710
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:66
@ PSQL_COMP_CASE_LOWER
Definition: settings.h:68
@ PSQL_COMP_CASE_PRESERVE_UPPER
Definition: settings.h:65
char * strtokx(const char *s, const char *whitespace, const char *delim, const char *quote, char escape, bool e_strings, bool del_quotes, int encoding)
Definition: stringutils.c:52
char * quote_if_needed(const char *source, const char *entails_quote, char quote, char escape, bool force_quote, int encoding)
Definition: stringutils.c:292
VariableSpace vars
Definition: settings.h:151
PSQL_COMP_CASE comp_case
Definition: settings.h:179
PGconn * db
Definition: settings.h:103
const char * progname
Definition: settings.h:142
struct _variable * next
Definition: variables.h:68
char * name
Definition: variables.h:64
char * value
Definition: variables.h:65
Definition: regguts.h:323
Definition: c.h:658
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:719
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