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