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