2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2018, PostgreSQL Global Development Group
6 * src/bin/psql/tab-complete.c
9 /*----------------------------------------------------------------------
10 * This file implements a somewhat more sophisticated readline "TAB
11 * completion" in psql. It is not intended to be AI, to replace
12 * learning SQL, or to relieve you from thinking about what you're
13 * doing. Also it does not always give you all the syntactically legal
14 * completions, only those that are the most common or the ones that
15 * the programmer felt most like implementing.
17 * CAVEAT: Tab completion causes queries to be sent to the backend.
18 * The number of tuples returned gets limited, in most default
19 * installations to 1000, but if you still don't like this prospect,
20 * you can turn off tab completion in your ~/.inputrc (or else
21 * ${INPUTRC}) file so:
24 * set disable-completion on
27 * See `man 3 readline' or `info readline' for the full details.
30 * - Quotes, parentheses, and other funny characters are not handled
31 * all that gracefully.
32 *----------------------------------------------------------------------
35 #include "postgres_fe.h"
36 #include "tab-complete.h"
39 /* If we don't have this, we might as well forget about the whole thing: */
44 #include "catalog/pg_class_d.h"
47 #include "pqexpbuffer.h"
50 #include "stringutils.h"
52 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
53 #define filename_completion_function rl_filename_completion_function
55 /* missing in some header files */
56 extern char *filename_completion_function();
59 #ifdef HAVE_RL_COMPLETION_MATCHES
60 #define completion_matches rl_completion_matches
63 /* word break characters */
64 #define WORD_BREAKS "\t\n@$><=;|&{() "
67 * Since readline doesn't let us pass any state through to the tab completion
68 * callback, we have to use this global variable to let get_previous_words()
69 * get at the previous lines of the current command. Ick.
71 PQExpBuffer tab_completion_query_buf = NULL;
74 * In some situations, the query to find out what names are available to
75 * complete with must vary depending on server version. We handle this by
76 * storing a list of queries, each tagged with the minimum server version
77 * it will work for. Each list must be stored in descending server version
78 * order, so that the first satisfactory query is the one to use.
80 * When the query string is otherwise constant, an array of VersionedQuery
81 * suffices. Terminate the array with an entry having min_server_version = 0.
82 * That entry's query string can be a query that works in all supported older
83 * server versions, or NULL to give up and do no completion.
85 typedef struct VersionedQuery
87 int min_server_version;
92 * This struct is used to define "schema queries", which are custom-built
93 * to obtain possibly-schema-qualified names of database objects. There is
94 * enough similarity in the structure that we don't want to repeat it each
95 * time. So we put the components of each query into this struct and
96 * assemble them with the common boilerplate in _complete_from_query().
98 * As with VersionedQuery, we can use an array of these if the query details
99 * must vary across versions.
101 typedef struct SchemaQuery
104 * If not zero, minimum server version this struct applies to. If not
105 * zero, there should be a following struct with a smaller minimum server
106 * version; use catname == NULL in the last entry if we should do nothing.
108 int min_server_version;
111 * Name of catalog or catalogs to be queried, with alias, eg.
112 * "pg_catalog.pg_class c". Note that "pg_namespace n" will be added.
117 * Selection condition --- only rows meeting this condition are candidates
118 * to display. If catname mentions multiple tables, include the necessary
119 * join condition here. For example, this might look like "c.relkind = "
120 * CppAsString2(RELKIND_RELATION). Write NULL (not an empty string) if
123 const char *selcondition;
126 * Visibility condition --- which rows are visible without schema
127 * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
129 const char *viscondition;
132 * Namespace --- name of field to join to pg_namespace.oid. For example,
135 const char *namespace;
138 * Result --- the appropriately-quoted name to return, in the case of an
139 * unqualified name. For example, "pg_catalog.quote_ident(c.relname)".
144 * In some cases a different result must be used for qualified names.
145 * Enter that here, or write NULL if result can be used.
147 const char *qualresult;
151 /* Store maximum number of records we want from database queries
152 * (implemented via SELECT ... LIMIT xx).
154 static int completion_max_records;
157 * Communication variables set by COMPLETE_WITH_FOO macros and then used by
158 * the completion callback functions. Ugly but there is no better way.
160 static const char *completion_charp; /* to pass a string */
161 static const char *const *completion_charpp; /* to pass a list of strings */
162 static const char *completion_info_charp; /* to pass a second string */
163 static const char *completion_info_charp2; /* to pass a third string */
164 static const VersionedQuery *completion_vquery; /* to pass a VersionedQuery */
165 static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
166 static bool completion_case_sensitive; /* completion is case sensitive */
169 * A few macros to ease typing. You can use these to complete the given
171 * 1) The results from a query you pass it. (Perhaps one of those below?)
172 * We support both simple and versioned queries.
173 * 2) The results from a schema query you pass it.
174 * We support both simple and versioned schema queries.
175 * 3) The items from a null-pointer-terminated list (with or without
176 * case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
177 * 4) A string constant.
178 * 5) The list of attributes of the given table (possibly schema-qualified).
179 * 6/ The list of arguments to the given function (possibly schema-qualified).
181 #define COMPLETE_WITH_QUERY(query) \
183 completion_charp = query; \
184 matches = completion_matches(text, complete_from_query); \
187 #define COMPLETE_WITH_VERSIONED_QUERY(query) \
189 completion_vquery = query; \
190 matches = completion_matches(text, complete_from_versioned_query); \
193 #define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
195 completion_squery = &(query); \
196 completion_charp = addon; \
197 matches = completion_matches(text, complete_from_schema_query); \
200 #define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(query, addon) \
202 completion_squery = query; \
203 completion_vquery = addon; \
204 matches = completion_matches(text, complete_from_versioned_schema_query); \
207 #define COMPLETE_WITH_LIST_CS(list) \
209 completion_charpp = list; \
210 completion_case_sensitive = true; \
211 matches = completion_matches(text, complete_from_list); \
214 #define COMPLETE_WITH_LIST(list) \
216 completion_charpp = list; \
217 completion_case_sensitive = false; \
218 matches = completion_matches(text, complete_from_list); \
221 #define COMPLETE_WITH_CONST(string) \
223 completion_charp = string; \
224 completion_case_sensitive = false; \
225 matches = completion_matches(text, complete_from_const); \
228 #define COMPLETE_WITH_ATTR(relation, addon) \
230 char *_completion_schema; \
231 char *_completion_table; \
233 _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
234 false, false, pset.encoding); \
235 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
236 false, false, pset.encoding); \
237 _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
238 false, false, pset.encoding); \
239 if (_completion_table == NULL) \
241 completion_charp = Query_for_list_of_attributes addon; \
242 completion_info_charp = relation; \
246 completion_charp = Query_for_list_of_attributes_with_schema addon; \
247 completion_info_charp = _completion_table; \
248 completion_info_charp2 = _completion_schema; \
250 matches = completion_matches(text, complete_from_query); \
253 #define COMPLETE_WITH_ENUM_VALUE(type) \
255 char *_completion_schema; \
256 char *_completion_type; \
258 _completion_schema = strtokx(type, " \t\n\r", ".", "\"", 0, \
259 false, false, pset.encoding); \
260 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
261 false, false, pset.encoding); \
262 _completion_type = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
263 false, false, pset.encoding); \
264 if (_completion_type == NULL)\
266 completion_charp = Query_for_list_of_enum_values; \
267 completion_info_charp = type; \
271 completion_charp = Query_for_list_of_enum_values_with_schema; \
272 completion_info_charp = _completion_type; \
273 completion_info_charp2 = _completion_schema; \
275 matches = completion_matches(text, complete_from_query); \
278 #define COMPLETE_WITH_FUNCTION_ARG(function) \
280 char *_completion_schema; \
281 char *_completion_function; \
283 _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
284 false, false, pset.encoding); \
285 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
286 false, false, pset.encoding); \
287 _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
288 false, false, pset.encoding); \
289 if (_completion_function == NULL) \
291 completion_charp = Query_for_list_of_arguments; \
292 completion_info_charp = function; \
296 completion_charp = Query_for_list_of_arguments_with_schema; \
297 completion_info_charp = _completion_function; \
298 completion_info_charp2 = _completion_schema; \
300 matches = completion_matches(text, complete_from_query); \
304 * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
305 * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
307 #define COMPLETE_WITH_LIST2(s1, s2) \
309 static const char *const list[] = { s1, s2, NULL }; \
310 COMPLETE_WITH_LIST(list); \
313 #define COMPLETE_WITH_LIST3(s1, s2, s3) \
315 static const char *const list[] = { s1, s2, s3, NULL }; \
316 COMPLETE_WITH_LIST(list); \
319 #define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
321 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
322 COMPLETE_WITH_LIST(list); \
325 #define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
327 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
328 COMPLETE_WITH_LIST(list); \
331 #define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \
333 static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \
334 COMPLETE_WITH_LIST(list); \
337 #define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \
339 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \
340 COMPLETE_WITH_LIST(list); \
343 #define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \
345 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \
346 COMPLETE_WITH_LIST(list); \
349 #define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
351 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
352 COMPLETE_WITH_LIST(list); \
355 #define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
357 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
358 COMPLETE_WITH_LIST(list); \
362 * Likewise for COMPLETE_WITH_LIST_CS.
364 #define COMPLETE_WITH_LIST_CS2(s1, s2) \
366 static const char *const list[] = { s1, s2, NULL }; \
367 COMPLETE_WITH_LIST_CS(list); \
370 #define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
372 static const char *const list[] = { s1, s2, s3, NULL }; \
373 COMPLETE_WITH_LIST_CS(list); \
376 #define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
378 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
379 COMPLETE_WITH_LIST_CS(list); \
382 #define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
384 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
385 COMPLETE_WITH_LIST_CS(list); \
389 * Assembly instructions for schema queries
392 static const SchemaQuery Query_for_list_of_aggregates[] = {
394 .min_server_version = 110000,
395 .catname = "pg_catalog.pg_proc p",
396 .selcondition = "p.prokind = 'a'",
397 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
398 .namespace = "p.pronamespace",
399 .result = "pg_catalog.quote_ident(p.proname)",
402 .catname = "pg_catalog.pg_proc p",
403 .selcondition = "p.proisagg",
404 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
405 .namespace = "p.pronamespace",
406 .result = "pg_catalog.quote_ident(p.proname)",
410 static const SchemaQuery Query_for_list_of_datatypes = {
411 .catname = "pg_catalog.pg_type t",
412 /* selcondition --- ignore table rowtypes and array types */
413 .selcondition = "(t.typrelid = 0 "
414 " OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
415 " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
416 "AND t.typname !~ '^_'",
417 .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
418 .namespace = "t.typnamespace",
419 .result = "pg_catalog.format_type(t.oid, NULL)",
420 .qualresult = "pg_catalog.quote_ident(t.typname)",
423 static const SchemaQuery Query_for_list_of_domains = {
424 .catname = "pg_catalog.pg_type t",
425 .selcondition = "t.typtype = 'd'",
426 .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
427 .namespace = "t.typnamespace",
428 .result = "pg_catalog.quote_ident(t.typname)",
431 /* Note: this intentionally accepts aggregates as well as plain functions */
432 static const SchemaQuery Query_for_list_of_functions[] = {
434 .min_server_version = 110000,
435 .catname = "pg_catalog.pg_proc p",
436 .selcondition = "p.prokind != 'p'",
437 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
438 .namespace = "p.pronamespace",
439 .result = "pg_catalog.quote_ident(p.proname)",
442 .catname = "pg_catalog.pg_proc p",
443 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
444 .namespace = "p.pronamespace",
445 .result = "pg_catalog.quote_ident(p.proname)",
449 static const SchemaQuery Query_for_list_of_indexes = {
450 .catname = "pg_catalog.pg_class c",
452 "c.relkind IN (" CppAsString2(RELKIND_INDEX) ", "
453 CppAsString2(RELKIND_PARTITIONED_INDEX) ")",
454 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
455 .namespace = "c.relnamespace",
456 .result = "pg_catalog.quote_ident(c.relname)",
459 static const SchemaQuery Query_for_list_of_procedures[] = {
461 .min_server_version = 110000,
462 .catname = "pg_catalog.pg_proc p",
463 .selcondition = "p.prokind = 'p'",
464 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
465 .namespace = "p.pronamespace",
466 .result = "pg_catalog.quote_ident(p.proname)",
469 /* not supported in older versions */
474 static const SchemaQuery Query_for_list_of_routines = {
475 .catname = "pg_catalog.pg_proc p",
476 .viscondition = "pg_catalog.pg_function_is_visible(p.oid)",
477 .namespace = "p.pronamespace",
478 .result = "pg_catalog.quote_ident(p.proname)",
481 static const SchemaQuery Query_for_list_of_sequences = {
482 .catname = "pg_catalog.pg_class c",
483 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
484 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
485 .namespace = "c.relnamespace",
486 .result = "pg_catalog.quote_ident(c.relname)",
489 static const SchemaQuery Query_for_list_of_foreign_tables = {
490 .catname = "pg_catalog.pg_class c",
491 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
492 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
493 .namespace = "c.relnamespace",
494 .result = "pg_catalog.quote_ident(c.relname)",
497 static const SchemaQuery Query_for_list_of_tables = {
498 .catname = "pg_catalog.pg_class c",
500 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
501 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
502 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
503 .namespace = "c.relnamespace",
504 .result = "pg_catalog.quote_ident(c.relname)",
507 static const SchemaQuery Query_for_list_of_partitioned_tables = {
508 .catname = "pg_catalog.pg_class c",
509 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
510 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
511 .namespace = "c.relnamespace",
512 .result = "pg_catalog.quote_ident(c.relname)",
515 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
516 .catname = "pg_catalog.pg_constraint c",
517 .selcondition = "c.conrelid <> 0",
518 .viscondition = "true", /* there is no pg_constraint_is_visible */
519 .namespace = "c.connamespace",
520 .result = "pg_catalog.quote_ident(c.conname)",
523 /* Relations supporting INSERT, UPDATE or DELETE */
524 static const SchemaQuery Query_for_list_of_updatables = {
525 .catname = "pg_catalog.pg_class c",
527 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
528 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
529 CppAsString2(RELKIND_VIEW) ", "
530 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
531 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
532 .namespace = "c.relnamespace",
533 .result = "pg_catalog.quote_ident(c.relname)",
536 static const SchemaQuery Query_for_list_of_relations = {
537 .catname = "pg_catalog.pg_class c",
538 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
539 .namespace = "c.relnamespace",
540 .result = "pg_catalog.quote_ident(c.relname)",
543 static const SchemaQuery Query_for_list_of_tsvmf = {
544 .catname = "pg_catalog.pg_class c",
546 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
547 CppAsString2(RELKIND_SEQUENCE) ", "
548 CppAsString2(RELKIND_VIEW) ", "
549 CppAsString2(RELKIND_MATVIEW) ", "
550 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
551 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
552 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
553 .namespace = "c.relnamespace",
554 .result = "pg_catalog.quote_ident(c.relname)",
557 static const SchemaQuery Query_for_list_of_tmf = {
558 .catname = "pg_catalog.pg_class c",
560 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
561 CppAsString2(RELKIND_MATVIEW) ", "
562 CppAsString2(RELKIND_FOREIGN_TABLE) ")",
563 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
564 .namespace = "c.relnamespace",
565 .result = "pg_catalog.quote_ident(c.relname)",
568 static const SchemaQuery Query_for_list_of_tpm = {
569 .catname = "pg_catalog.pg_class c",
571 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
572 CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
573 CppAsString2(RELKIND_MATVIEW) ")",
574 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
575 .namespace = "c.relnamespace",
576 .result = "pg_catalog.quote_ident(c.relname)",
579 static const SchemaQuery Query_for_list_of_tm = {
580 .catname = "pg_catalog.pg_class c",
582 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
583 CppAsString2(RELKIND_MATVIEW) ")",
584 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
585 .namespace = "c.relnamespace",
586 .result = "pg_catalog.quote_ident(c.relname)",
589 static const SchemaQuery Query_for_list_of_views = {
590 .catname = "pg_catalog.pg_class c",
591 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
592 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
593 .namespace = "c.relnamespace",
594 .result = "pg_catalog.quote_ident(c.relname)",
597 static const SchemaQuery Query_for_list_of_matviews = {
598 .catname = "pg_catalog.pg_class c",
599 .selcondition = "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
600 .viscondition = "pg_catalog.pg_table_is_visible(c.oid)",
601 .namespace = "c.relnamespace",
602 .result = "pg_catalog.quote_ident(c.relname)",
605 static const SchemaQuery Query_for_list_of_statistics = {
606 .catname = "pg_catalog.pg_statistic_ext s",
607 .viscondition = "pg_catalog.pg_statistics_obj_is_visible(s.oid)",
608 .namespace = "s.stxnamespace",
609 .result = "pg_catalog.quote_ident(s.stxname)",
614 * Queries to get lists of names of various kinds of things, possibly
615 * restricted to names matching a partially entered name. In these queries,
616 * the first %s will be replaced by the text entered so far (suitably escaped
617 * to become a SQL literal string). %d will be replaced by the length of the
618 * string (in unescaped form). A second and third %s, if present, will be
619 * replaced by a suitably-escaped version of the string provided in
620 * completion_info_charp. A fourth and fifth %s are similarly replaced by
621 * completion_info_charp2.
623 * Beware that the allowed sequences of %s and %d are determined by
624 * _complete_from_query().
627 #define Query_for_list_of_attributes \
628 "SELECT pg_catalog.quote_ident(attname) "\
629 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
630 " WHERE c.oid = a.attrelid "\
631 " AND a.attnum > 0 "\
632 " AND NOT a.attisdropped "\
633 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
634 " AND (pg_catalog.quote_ident(relname)='%s' "\
635 " OR '\"' || relname || '\"'='%s') "\
636 " AND pg_catalog.pg_table_is_visible(c.oid)"
638 #define Query_for_list_of_attributes_with_schema \
639 "SELECT pg_catalog.quote_ident(attname) "\
640 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
641 " WHERE c.oid = a.attrelid "\
642 " AND n.oid = c.relnamespace "\
643 " AND a.attnum > 0 "\
644 " AND NOT a.attisdropped "\
645 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
646 " AND (pg_catalog.quote_ident(relname)='%s' "\
647 " OR '\"' || relname || '\"' ='%s') "\
648 " AND (pg_catalog.quote_ident(nspname)='%s' "\
649 " OR '\"' || nspname || '\"' ='%s') "
651 #define Query_for_list_of_enum_values \
652 "SELECT pg_catalog.quote_literal(enumlabel) "\
653 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t "\
654 " WHERE t.oid = e.enumtypid "\
655 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
656 " AND (pg_catalog.quote_ident(typname)='%s' "\
657 " OR '\"' || typname || '\"'='%s') "\
658 " AND pg_catalog.pg_type_is_visible(t.oid)"
660 #define Query_for_list_of_enum_values_with_schema \
661 "SELECT pg_catalog.quote_literal(enumlabel) "\
662 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
663 " WHERE t.oid = e.enumtypid "\
664 " AND n.oid = t.typnamespace "\
665 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
666 " AND (pg_catalog.quote_ident(typname)='%s' "\
667 " OR '\"' || typname || '\"'='%s') "\
668 " AND (pg_catalog.quote_ident(nspname)='%s' "\
669 " OR '\"' || nspname || '\"' ='%s') "
671 #define Query_for_list_of_template_databases \
672 "SELECT pg_catalog.quote_ident(d.datname) "\
673 " FROM pg_catalog.pg_database d "\
674 " WHERE substring(pg_catalog.quote_ident(d.datname),1,%d)='%s' "\
675 " AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
677 #define Query_for_list_of_databases \
678 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
679 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
681 #define Query_for_list_of_tablespaces \
682 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
683 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
685 #define Query_for_list_of_encodings \
686 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
687 " FROM pg_catalog.pg_conversion "\
688 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
690 #define Query_for_list_of_languages \
691 "SELECT pg_catalog.quote_ident(lanname) "\
692 " FROM pg_catalog.pg_language "\
693 " WHERE lanname != 'internal' "\
694 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
696 #define Query_for_list_of_schemas \
697 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
698 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
700 #define Query_for_list_of_alter_system_set_vars \
702 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
703 " WHERE context != 'internal' "\
704 " UNION ALL SELECT 'all') ss "\
705 " WHERE substring(name,1,%d)='%s'"
707 #define Query_for_list_of_set_vars \
709 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
710 " WHERE context IN ('user', 'superuser') "\
711 " UNION ALL SELECT 'constraints' "\
712 " UNION ALL SELECT 'transaction' "\
713 " UNION ALL SELECT 'session' "\
714 " UNION ALL SELECT 'role' "\
715 " UNION ALL SELECT 'tablespace' "\
716 " UNION ALL SELECT 'all') ss "\
717 " WHERE substring(name,1,%d)='%s'"
719 #define Query_for_list_of_show_vars \
721 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
722 " UNION ALL SELECT 'session authorization' "\
723 " UNION ALL SELECT 'all') ss "\
724 " WHERE substring(name,1,%d)='%s'"
726 #define Query_for_list_of_roles \
727 " SELECT pg_catalog.quote_ident(rolname) "\
728 " FROM pg_catalog.pg_roles "\
729 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
731 #define Query_for_list_of_grant_roles \
732 " SELECT pg_catalog.quote_ident(rolname) "\
733 " FROM pg_catalog.pg_roles "\
734 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
735 " UNION ALL SELECT 'PUBLIC'"\
736 " UNION ALL SELECT 'CURRENT_USER'"\
737 " UNION ALL SELECT 'SESSION_USER'"
739 /* the silly-looking length condition is just to eat up the current word */
740 #define Query_for_table_owning_index \
741 "SELECT pg_catalog.quote_ident(c1.relname) "\
742 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
743 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
744 " and (%d = pg_catalog.length('%s'))"\
745 " and pg_catalog.quote_ident(c2.relname)='%s'"\
746 " and pg_catalog.pg_table_is_visible(c2.oid)"
748 /* the silly-looking length condition is just to eat up the current word */
749 #define Query_for_index_of_table \
750 "SELECT pg_catalog.quote_ident(c2.relname) "\
751 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
752 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
753 " and (%d = pg_catalog.length('%s'))"\
754 " and pg_catalog.quote_ident(c1.relname)='%s'"\
755 " and pg_catalog.pg_table_is_visible(c2.oid)"
757 /* the silly-looking length condition is just to eat up the current word */
758 #define Query_for_constraint_of_table \
759 "SELECT pg_catalog.quote_ident(conname) "\
760 " FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
761 " WHERE c1.oid=conrelid and (%d = pg_catalog.length('%s'))"\
762 " and pg_catalog.quote_ident(c1.relname)='%s'"\
763 " and pg_catalog.pg_table_is_visible(c1.oid)"
765 #define Query_for_all_table_constraints \
766 "SELECT pg_catalog.quote_ident(conname) "\
767 " FROM pg_catalog.pg_constraint c "\
768 " WHERE c.conrelid <> 0 "
770 /* the silly-looking length condition is just to eat up the current word */
771 #define Query_for_constraint_of_type \
772 "SELECT pg_catalog.quote_ident(conname) "\
773 " FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
774 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
775 " and pg_catalog.quote_ident(t.typname)='%s'"\
776 " and pg_catalog.pg_type_is_visible(t.oid)"
778 /* the silly-looking length condition is just to eat up the current word */
779 #define Query_for_list_of_tables_for_constraint \
780 "SELECT pg_catalog.quote_ident(relname) "\
781 " FROM pg_catalog.pg_class"\
782 " WHERE (%d = pg_catalog.length('%s'))"\
784 " (SELECT conrelid FROM pg_catalog.pg_constraint "\
785 " WHERE pg_catalog.quote_ident(conname)='%s')"
787 /* the silly-looking length condition is just to eat up the current word */
788 #define Query_for_rule_of_table \
789 "SELECT pg_catalog.quote_ident(rulename) "\
790 " FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
791 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
792 " and pg_catalog.quote_ident(c1.relname)='%s'"\
793 " and pg_catalog.pg_table_is_visible(c1.oid)"
795 /* the silly-looking length condition is just to eat up the current word */
796 #define Query_for_list_of_tables_for_rule \
797 "SELECT pg_catalog.quote_ident(relname) "\
798 " FROM pg_catalog.pg_class"\
799 " WHERE (%d = pg_catalog.length('%s'))"\
801 " (SELECT ev_class FROM pg_catalog.pg_rewrite "\
802 " WHERE pg_catalog.quote_ident(rulename)='%s')"
804 /* the silly-looking length condition is just to eat up the current word */
805 #define Query_for_trigger_of_table \
806 "SELECT pg_catalog.quote_ident(tgname) "\
807 " FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
808 " WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
809 " and pg_catalog.quote_ident(c1.relname)='%s'"\
810 " and pg_catalog.pg_table_is_visible(c1.oid)"\
811 " and not tgisinternal"
813 /* the silly-looking length condition is just to eat up the current word */
814 #define Query_for_list_of_tables_for_trigger \
815 "SELECT pg_catalog.quote_ident(relname) "\
816 " FROM pg_catalog.pg_class"\
817 " WHERE (%d = pg_catalog.length('%s'))"\
819 " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
820 " WHERE pg_catalog.quote_ident(tgname)='%s')"
822 #define Query_for_list_of_ts_configurations \
823 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
824 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
826 #define Query_for_list_of_ts_dictionaries \
827 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
828 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
830 #define Query_for_list_of_ts_parsers \
831 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
832 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
834 #define Query_for_list_of_ts_templates \
835 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
836 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
838 #define Query_for_list_of_fdws \
839 " SELECT pg_catalog.quote_ident(fdwname) "\
840 " FROM pg_catalog.pg_foreign_data_wrapper "\
841 " WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
843 #define Query_for_list_of_servers \
844 " SELECT pg_catalog.quote_ident(srvname) "\
845 " FROM pg_catalog.pg_foreign_server "\
846 " WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
848 #define Query_for_list_of_user_mappings \
849 " SELECT pg_catalog.quote_ident(usename) "\
850 " FROM pg_catalog.pg_user_mappings "\
851 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
853 #define Query_for_list_of_access_methods \
854 " SELECT pg_catalog.quote_ident(amname) "\
855 " FROM pg_catalog.pg_am "\
856 " WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
858 /* the silly-looking length condition is just to eat up the current word */
859 #define Query_for_list_of_arguments \
860 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
861 " FROM pg_catalog.pg_proc "\
862 " WHERE (%d = pg_catalog.length('%s'))"\
863 " AND (pg_catalog.quote_ident(proname)='%s'"\
864 " OR '\"' || proname || '\"'='%s') "\
865 " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
867 /* the silly-looking length condition is just to eat up the current word */
868 #define Query_for_list_of_arguments_with_schema \
869 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
870 " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
871 " WHERE (%d = pg_catalog.length('%s'))"\
872 " AND n.oid = p.pronamespace "\
873 " AND (pg_catalog.quote_ident(proname)='%s' "\
874 " OR '\"' || proname || '\"' ='%s') "\
875 " AND (pg_catalog.quote_ident(nspname)='%s' "\
876 " OR '\"' || nspname || '\"' ='%s') "
878 #define Query_for_list_of_extensions \
879 " SELECT pg_catalog.quote_ident(extname) "\
880 " FROM pg_catalog.pg_extension "\
881 " WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
883 #define Query_for_list_of_available_extensions \
884 " SELECT pg_catalog.quote_ident(name) "\
885 " FROM pg_catalog.pg_available_extensions "\
886 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
888 /* the silly-looking length condition is just to eat up the current word */
889 #define Query_for_list_of_available_extension_versions \
890 " SELECT pg_catalog.quote_ident(version) "\
891 " FROM pg_catalog.pg_available_extension_versions "\
892 " WHERE (%d = pg_catalog.length('%s'))"\
893 " AND pg_catalog.quote_ident(name)='%s'"
895 /* the silly-looking length condition is just to eat up the current word */
896 #define Query_for_list_of_available_extension_versions_with_TO \
897 " SELECT 'TO ' || pg_catalog.quote_ident(version) "\
898 " FROM pg_catalog.pg_available_extension_versions "\
899 " WHERE (%d = pg_catalog.length('%s'))"\
900 " AND pg_catalog.quote_ident(name)='%s'"
902 #define Query_for_list_of_prepared_statements \
903 " SELECT pg_catalog.quote_ident(name) "\
904 " FROM pg_catalog.pg_prepared_statements "\
905 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
907 #define Query_for_list_of_event_triggers \
908 " SELECT pg_catalog.quote_ident(evtname) "\
909 " FROM pg_catalog.pg_event_trigger "\
910 " WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
912 #define Query_for_list_of_tablesample_methods \
913 " SELECT pg_catalog.quote_ident(proname) "\
914 " FROM pg_catalog.pg_proc "\
915 " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
916 " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
917 " substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
919 #define Query_for_list_of_policies \
920 " SELECT pg_catalog.quote_ident(polname) "\
921 " FROM pg_catalog.pg_policy "\
922 " WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
924 #define Query_for_list_of_tables_for_policy \
925 "SELECT pg_catalog.quote_ident(relname) "\
926 " FROM pg_catalog.pg_class"\
927 " WHERE (%d = pg_catalog.length('%s'))"\
929 " (SELECT polrelid FROM pg_catalog.pg_policy "\
930 " WHERE pg_catalog.quote_ident(polname)='%s')"
932 #define Query_for_enum \
933 " SELECT name FROM ( "\
934 " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
935 " FROM pg_catalog.pg_settings "\
936 " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
938 " SELECT 'DEFAULT' ) ss "\
939 " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
941 /* the silly-looking length condition is just to eat up the current word */
942 #define Query_for_partition_of_table \
943 "SELECT pg_catalog.quote_ident(c2.relname) "\
944 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i"\
945 " WHERE c1.oid=i.inhparent and i.inhrelid=c2.oid"\
946 " and (%d = pg_catalog.length('%s'))"\
947 " and pg_catalog.quote_ident(c1.relname)='%s'"\
948 " and pg_catalog.pg_table_is_visible(c2.oid)"\
949 " and c2.relispartition = 'true'"
952 * These object types were introduced later than our support cutoff of
953 * server version 7.4. We use the VersionedQuery infrastructure so that
954 * we don't send certain-to-fail queries to older servers.
957 static const VersionedQuery Query_for_list_of_publications[] = {
959 " SELECT pg_catalog.quote_ident(pubname) "
960 " FROM pg_catalog.pg_publication "
961 " WHERE substring(pg_catalog.quote_ident(pubname),1,%d)='%s'"
966 static const VersionedQuery Query_for_list_of_subscriptions[] = {
968 " SELECT pg_catalog.quote_ident(s.subname) "
969 " FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "
970 " WHERE substring(pg_catalog.quote_ident(s.subname),1,%d)='%s' "
971 " AND d.datname = pg_catalog.current_database() "
972 " AND s.subdbid = d.oid"
978 * This is a list of all "things" in Pgsql, which can show up after CREATE or
979 * DROP; and there is also a query to get a list of them.
985 const char *query; /* simple query, or NULL */
986 const VersionedQuery *vquery; /* versioned query, or NULL */
987 const SchemaQuery *squery; /* schema query, or NULL */
988 const bits32 flags; /* visibility flags, see below */
991 #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
992 #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
993 #define THING_NO_ALTER (1 << 2) /* should not show up after ALTER */
994 #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
996 static const pgsql_thing_t words_after_create[] = {
997 {"ACCESS METHOD", NULL, NULL, NULL, THING_NO_ALTER},
998 {"AGGREGATE", NULL, NULL, Query_for_list_of_aggregates},
999 {"CAST", NULL, NULL, NULL}, /* Casts have complex structures for names, so
1001 {"COLLATION", "SELECT pg_catalog.quote_ident(collname) FROM pg_catalog.pg_collation WHERE collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding())) AND substring(pg_catalog.quote_ident(collname),1,%d)='%s'"},
1004 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
1005 * to be used only by pg_dump.
1007 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, NULL, THING_NO_SHOW},
1008 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
1009 {"DATABASE", Query_for_list_of_databases},
1010 {"DEFAULT PRIVILEGES", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1011 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, NULL, THING_NO_SHOW},
1012 {"DOMAIN", NULL, NULL, &Query_for_list_of_domains},
1013 {"EVENT TRIGGER", NULL, NULL, NULL},
1014 {"EXTENSION", Query_for_list_of_extensions},
1015 {"FOREIGN DATA WRAPPER", NULL, NULL, NULL},
1016 {"FOREIGN TABLE", NULL, NULL, NULL},
1017 {"FUNCTION", NULL, NULL, Query_for_list_of_functions},
1018 {"GROUP", Query_for_list_of_roles},
1019 {"INDEX", NULL, NULL, &Query_for_list_of_indexes},
1020 {"LANGUAGE", Query_for_list_of_languages},
1021 {"LARGE OBJECT", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1022 {"MATERIALIZED VIEW", NULL, NULL, &Query_for_list_of_matviews},
1023 {"OPERATOR", NULL, NULL, NULL}, /* Querying for this is probably not such
1025 {"OWNED", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_ALTER}, /* for DROP OWNED BY ... */
1026 {"PARSER", Query_for_list_of_ts_parsers, NULL, NULL, THING_NO_SHOW},
1027 {"POLICY", NULL, NULL, NULL},
1028 {"PROCEDURE", NULL, NULL, Query_for_list_of_procedures},
1029 {"PUBLICATION", NULL, Query_for_list_of_publications},
1030 {"ROLE", Query_for_list_of_roles},
1031 {"ROUTINE", NULL, NULL, &Query_for_list_of_routines, THING_NO_CREATE},
1032 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
1033 {"SCHEMA", Query_for_list_of_schemas},
1034 {"SEQUENCE", NULL, NULL, &Query_for_list_of_sequences},
1035 {"SERVER", Query_for_list_of_servers},
1036 {"STATISTICS", NULL, NULL, &Query_for_list_of_statistics},
1037 {"SUBSCRIPTION", NULL, Query_for_list_of_subscriptions},
1038 {"SYSTEM", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1039 {"TABLE", NULL, NULL, &Query_for_list_of_tables},
1040 {"TABLESPACE", Query_for_list_of_tablespaces},
1041 {"TEMP", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE
1043 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, NULL, THING_NO_SHOW},
1044 {"TEMPORARY", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMPORARY
1046 {"TEXT SEARCH", NULL, NULL, NULL},
1047 {"TRANSFORM", NULL, NULL, NULL},
1048 {"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s' AND NOT tgisinternal"},
1049 {"TYPE", NULL, NULL, &Query_for_list_of_datatypes},
1050 {"UNIQUE", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNIQUE
1052 {"UNLOGGED", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNLOGGED
1054 {"USER", Query_for_list_of_roles " UNION SELECT 'MAPPING FOR'"},
1055 {"USER MAPPING FOR", NULL, NULL, NULL},
1056 {"VIEW", NULL, NULL, &Query_for_list_of_views},
1057 {NULL} /* end of list */
1061 /* Forward declaration of functions */
1062 static char **psql_completion(const char *text, int start, int end);
1063 static char *create_command_generator(const char *text, int state);
1064 static char *drop_command_generator(const char *text, int state);
1065 static char *alter_command_generator(const char *text, int state);
1066 static char *complete_from_query(const char *text, int state);
1067 static char *complete_from_versioned_query(const char *text, int state);
1068 static char *complete_from_schema_query(const char *text, int state);
1069 static char *complete_from_versioned_schema_query(const char *text, int state);
1070 static char *_complete_from_query(const char *simple_query,
1071 const SchemaQuery *schema_query,
1072 const char *text, int state);
1073 static char *complete_from_list(const char *text, int state);
1074 static char *complete_from_const(const char *text, int state);
1075 static void append_variable_names(char ***varnames, int *nvars,
1076 int *maxvars, const char *varname,
1077 const char *prefix, const char *suffix);
1078 static char **complete_from_variables(const char *text,
1079 const char *prefix, const char *suffix, bool need_value);
1080 static char *complete_from_files(const char *text, int state);
1082 static char *pg_strdup_keyword_case(const char *s, const char *ref);
1083 static char *escape_string(const char *text);
1084 static PGresult *exec_query(const char *query);
1086 static char **get_previous_words(int point, char **buffer, int *nwords);
1088 static char *get_guctype(const char *varname);
1091 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
1092 static char *dequote_file_name(char *text, char quote_char);
1097 * Initialize the readline library for our purposes.
1100 initialize_readline(void)
1102 rl_readline_name = (char *) pset.progname;
1103 rl_attempted_completion_function = psql_completion;
1105 rl_basic_word_break_characters = WORD_BREAKS;
1107 completion_max_records = 1000;
1110 * There is a variable rl_completion_query_items for this but apparently
1111 * it's not defined everywhere.
1116 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1117 * using case-insensitive or case-sensitive comparisons.
1119 * If pattern is NULL, it's a wild card that matches any word.
1120 * If pattern begins with '!', the result is negated, ie we check that 'word'
1121 * does *not* match any alternative appearing in the rest of 'pattern'.
1122 * Any alternative can end with '*' which is a wild card, i.e., it means
1123 * match any word that matches the characters so far. (We do not currently
1124 * support '*' elsewhere than the end of an alternative.)
1126 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1127 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1128 * just be written directly in patterns.)
1130 #define MatchAny NULL
1131 #define MatchAnyExcept(pattern) ("!" pattern)
1134 word_matches_internal(const char *pattern,
1136 bool case_sensitive)
1141 /* NULL pattern matches anything. */
1142 if (pattern == NULL)
1145 /* Handle negated patterns from the MatchAnyExcept macro. */
1146 if (*pattern == '!')
1147 return !word_matches_internal(pattern + 1, word, case_sensitive);
1149 /* Else consider each alternative in the pattern. */
1150 wordlen = strlen(word);
1155 /* Find end of current alternative. */
1157 while (*c != '\0' && *c != '|')
1159 /* Was there a wild card? (Assumes first alternative is not empty) */
1162 /* Yes, wildcard match? */
1163 patternlen = c - pattern - 1;
1164 if (wordlen >= patternlen &&
1166 strncmp(word, pattern, patternlen) == 0 :
1167 pg_strncasecmp(word, pattern, patternlen) == 0))
1172 /* No, plain match? */
1173 patternlen = c - pattern;
1174 if (wordlen == patternlen &&
1176 strncmp(word, pattern, wordlen) == 0 :
1177 pg_strncasecmp(word, pattern, wordlen) == 0))
1180 /* Out of alternatives? */
1183 /* Nope, try next alternative. */
1191 * There are enough matching calls below that it seems worth having these two
1192 * interface routines rather than including a third parameter in every call.
1194 * word_matches --- match case-insensitively.
1197 word_matches(const char *pattern, const char *word)
1199 return word_matches_internal(pattern, word, false);
1203 * word_matches_cs --- match case-sensitively.
1206 word_matches_cs(const char *pattern, const char *word)
1208 return word_matches_internal(pattern, word, true);
1212 * Check if the final character of 's' is 'c'.
1215 ends_with(const char *s, char c)
1217 size_t length = strlen(s);
1219 return (length > 0 && s[length - 1] == c);
1223 * The completion function.
1225 * According to readline spec this gets passed the text entered so far and its
1226 * start and end positions in the readline buffer. The return value is some
1227 * partially obscure list format that can be generated by readline's
1228 * completion_matches() function, so we don't have to worry about it.
1231 psql_completion(const char *text, int start, int end)
1233 /* This is the variable we'll return. */
1234 char **matches = NULL;
1236 /* Workspace for parsed words. */
1239 /* This array will contain pointers to parsed words. */
1240 char **previous_words;
1242 /* The number of words found on the input line. */
1243 int previous_words_count;
1246 * For compactness, we use these macros to reference previous_words[].
1247 * Caution: do not access a previous_words[] entry without having checked
1248 * previous_words_count to be sure it's valid. In most cases below, that
1249 * check is implicit in a TailMatches() or similar macro, but in some
1250 * places we have to check it explicitly.
1252 #define prev_wd (previous_words[0])
1253 #define prev2_wd (previous_words[1])
1254 #define prev3_wd (previous_words[2])
1255 #define prev4_wd (previous_words[3])
1256 #define prev5_wd (previous_words[4])
1257 #define prev6_wd (previous_words[5])
1258 #define prev7_wd (previous_words[6])
1259 #define prev8_wd (previous_words[7])
1260 #define prev9_wd (previous_words[8])
1262 /* Macros for matching the last N words before point, case-insensitively. */
1263 #define TailMatches1(p1) \
1264 (previous_words_count >= 1 && \
1265 word_matches(p1, prev_wd))
1267 #define TailMatches2(p2, p1) \
1268 (previous_words_count >= 2 && \
1269 word_matches(p1, prev_wd) && \
1270 word_matches(p2, prev2_wd))
1272 #define TailMatches3(p3, p2, p1) \
1273 (previous_words_count >= 3 && \
1274 word_matches(p1, prev_wd) && \
1275 word_matches(p2, prev2_wd) && \
1276 word_matches(p3, prev3_wd))
1278 #define TailMatches4(p4, p3, p2, p1) \
1279 (previous_words_count >= 4 && \
1280 word_matches(p1, prev_wd) && \
1281 word_matches(p2, prev2_wd) && \
1282 word_matches(p3, prev3_wd) && \
1283 word_matches(p4, prev4_wd))
1285 #define TailMatches5(p5, p4, p3, p2, p1) \
1286 (previous_words_count >= 5 && \
1287 word_matches(p1, prev_wd) && \
1288 word_matches(p2, prev2_wd) && \
1289 word_matches(p3, prev3_wd) && \
1290 word_matches(p4, prev4_wd) && \
1291 word_matches(p5, prev5_wd))
1293 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1294 (previous_words_count >= 6 && \
1295 word_matches(p1, prev_wd) && \
1296 word_matches(p2, prev2_wd) && \
1297 word_matches(p3, prev3_wd) && \
1298 word_matches(p4, prev4_wd) && \
1299 word_matches(p5, prev5_wd) && \
1300 word_matches(p6, prev6_wd))
1302 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1303 (previous_words_count >= 7 && \
1304 word_matches(p1, prev_wd) && \
1305 word_matches(p2, prev2_wd) && \
1306 word_matches(p3, prev3_wd) && \
1307 word_matches(p4, prev4_wd) && \
1308 word_matches(p5, prev5_wd) && \
1309 word_matches(p6, prev6_wd) && \
1310 word_matches(p7, prev7_wd))
1312 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1313 (previous_words_count >= 8 && \
1314 word_matches(p1, prev_wd) && \
1315 word_matches(p2, prev2_wd) && \
1316 word_matches(p3, prev3_wd) && \
1317 word_matches(p4, prev4_wd) && \
1318 word_matches(p5, prev5_wd) && \
1319 word_matches(p6, prev6_wd) && \
1320 word_matches(p7, prev7_wd) && \
1321 word_matches(p8, prev8_wd))
1323 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1324 (previous_words_count >= 9 && \
1325 word_matches(p1, prev_wd) && \
1326 word_matches(p2, prev2_wd) && \
1327 word_matches(p3, prev3_wd) && \
1328 word_matches(p4, prev4_wd) && \
1329 word_matches(p5, prev5_wd) && \
1330 word_matches(p6, prev6_wd) && \
1331 word_matches(p7, prev7_wd) && \
1332 word_matches(p8, prev8_wd) && \
1333 word_matches(p9, prev9_wd))
1335 /* Macros for matching the last N words before point, case-sensitively. */
1336 #define TailMatchesCS1(p1) \
1337 (previous_words_count >= 1 && \
1338 word_matches_cs(p1, prev_wd))
1339 #define TailMatchesCS2(p2, p1) \
1340 (previous_words_count >= 2 && \
1341 word_matches_cs(p1, prev_wd) && \
1342 word_matches_cs(p2, prev2_wd))
1343 #define TailMatchesCS3(p3, p2, p1) \
1344 (previous_words_count >= 3 && \
1345 word_matches_cs(p1, prev_wd) && \
1346 word_matches_cs(p2, prev2_wd) && \
1347 word_matches_cs(p3, prev3_wd))
1348 #define TailMatchesCS4(p4, p3, p2, p1) \
1349 (previous_words_count >= 4 && \
1350 word_matches_cs(p1, prev_wd) && \
1351 word_matches_cs(p2, prev2_wd) && \
1352 word_matches_cs(p3, prev3_wd) && \
1353 word_matches_cs(p4, prev4_wd))
1356 * Macros for matching N words beginning at the start of the line,
1357 * case-insensitively.
1359 #define Matches1(p1) \
1360 (previous_words_count == 1 && \
1362 #define Matches2(p1, p2) \
1363 (previous_words_count == 2 && \
1364 TailMatches2(p1, p2))
1365 #define Matches3(p1, p2, p3) \
1366 (previous_words_count == 3 && \
1367 TailMatches3(p1, p2, p3))
1368 #define Matches4(p1, p2, p3, p4) \
1369 (previous_words_count == 4 && \
1370 TailMatches4(p1, p2, p3, p4))
1371 #define Matches5(p1, p2, p3, p4, p5) \
1372 (previous_words_count == 5 && \
1373 TailMatches5(p1, p2, p3, p4, p5))
1374 #define Matches6(p1, p2, p3, p4, p5, p6) \
1375 (previous_words_count == 6 && \
1376 TailMatches6(p1, p2, p3, p4, p5, p6))
1377 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1378 (previous_words_count == 7 && \
1379 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1380 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1381 (previous_words_count == 8 && \
1382 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1383 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1384 (previous_words_count == 9 && \
1385 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1388 * Macros for matching N words at the start of the line, regardless of
1389 * what is after them, case-insensitively.
1391 #define HeadMatches1(p1) \
1392 (previous_words_count >= 1 && \
1393 word_matches(p1, previous_words[previous_words_count - 1]))
1395 #define HeadMatches2(p1, p2) \
1396 (previous_words_count >= 2 && \
1397 word_matches(p1, previous_words[previous_words_count - 1]) && \
1398 word_matches(p2, previous_words[previous_words_count - 2]))
1400 #define HeadMatches3(p1, p2, p3) \
1401 (previous_words_count >= 3 && \
1402 word_matches(p1, previous_words[previous_words_count - 1]) && \
1403 word_matches(p2, previous_words[previous_words_count - 2]) && \
1404 word_matches(p3, previous_words[previous_words_count - 3]))
1406 /* Known command-starting keywords. */
1407 static const char *const sql_commands[] = {
1408 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CALL", "CHECKPOINT", "CLOSE", "CLUSTER",
1409 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1410 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1411 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1412 "MOVE", "NOTIFY", "PREPARE",
1413 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1414 "RESET", "REVOKE", "ROLLBACK",
1415 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1416 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1420 /* psql's backslash commands. */
1421 static const char *const backslash_commands[] = {
1423 "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1424 "\\copyright", "\\crosstabview",
1425 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1426 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1427 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1428 "\\dm", "\\dn", "\\do", "\\dO", "\\dp",
1429 "\\drds", "\\dRs", "\\dRp", "\\ds", "\\dS",
1430 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1431 "\\e", "\\echo", "\\ef", "\\elif", "\\else", "\\encoding",
1432 "\\endif", "\\errverbose", "\\ev",
1434 "\\g", "\\gdesc", "\\gexec", "\\gset", "\\gx",
1435 "\\h", "\\help", "\\H",
1436 "\\i", "\\if", "\\ir",
1437 "\\l", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1439 "\\p", "\\password", "\\prompt", "\\pset",
1442 "\\s", "\\set", "\\setenv", "\\sf", "\\sv",
1443 "\\t", "\\T", "\\timing",
1452 (void) end; /* "end" is not used */
1454 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1455 rl_completion_append_character = ' ';
1458 /* Clear a few things. */
1459 completion_charp = NULL;
1460 completion_charpp = NULL;
1461 completion_info_charp = NULL;
1462 completion_info_charp2 = NULL;
1465 * Scan the input line to extract the words before our current position.
1466 * According to those we'll make some smart decisions on what the user is
1467 * probably intending to type.
1469 previous_words = get_previous_words(start,
1471 &previous_words_count);
1473 /* If current word is a backslash command, offer completions for that */
1474 if (text[0] == '\\')
1475 COMPLETE_WITH_LIST_CS(backslash_commands);
1477 /* If current word is a variable interpolation, handle that case */
1478 else if (text[0] == ':' && text[1] != ':')
1480 if (text[1] == '\'')
1481 matches = complete_from_variables(text, ":'", "'", true);
1482 else if (text[1] == '"')
1483 matches = complete_from_variables(text, ":\"", "\"", true);
1485 matches = complete_from_variables(text, ":", "", true);
1488 /* If no previous word, suggest one of the basic sql commands */
1489 else if (previous_words_count == 0)
1490 COMPLETE_WITH_LIST(sql_commands);
1493 /* complete with something you can create */
1494 else if (TailMatches1("CREATE"))
1495 matches = completion_matches(text, create_command_generator);
1497 /* DROP, but not DROP embedded in other commands */
1498 /* complete with something you can drop */
1499 else if (Matches1("DROP"))
1500 matches = completion_matches(text, drop_command_generator);
1505 else if (Matches2("ALTER", "TABLE"))
1506 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1507 "UNION SELECT 'ALL IN TABLESPACE'");
1509 /* ALTER something */
1510 else if (Matches1("ALTER"))
1511 matches = completion_matches(text, alter_command_generator);
1512 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1513 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1514 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1515 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1516 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1517 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1518 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1519 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1520 COMPLETE_WITH_CONST("SET TABLESPACE");
1521 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
1522 else if (Matches3("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
1523 COMPLETE_WITH_CONST("(");
1524 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> (...) */
1525 else if (Matches4("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny))
1527 if (ends_with(prev_wd, ')'))
1528 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1530 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1532 /* ALTER PUBLICATION <name> */
1533 else if (Matches3("ALTER", "PUBLICATION", MatchAny))
1534 COMPLETE_WITH_LIST5("ADD TABLE", "DROP TABLE", "OWNER TO", "RENAME TO", "SET");
1535 /* ALTER PUBLICATION <name> SET */
1536 else if (Matches4("ALTER", "PUBLICATION", MatchAny, "SET"))
1537 COMPLETE_WITH_LIST2("(", "TABLE");
1538 /* ALTER PUBLICATION <name> SET ( */
1539 else if (HeadMatches3("ALTER", "PUBLICATION", MatchAny) && TailMatches2("SET", "("))
1540 COMPLETE_WITH_CONST("publish");
1541 /* ALTER SUBSCRIPTION <name> */
1542 else if (Matches3("ALTER", "SUBSCRIPTION", MatchAny))
1543 COMPLETE_WITH_LIST7("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
1544 "RENAME TO", "REFRESH PUBLICATION", "SET");
1545 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION */
1546 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1547 TailMatches2("REFRESH", "PUBLICATION"))
1548 COMPLETE_WITH_CONST("WITH (");
1549 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
1550 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1551 TailMatches4("REFRESH", "PUBLICATION", "WITH", "("))
1552 COMPLETE_WITH_CONST("copy_data");
1553 /* ALTER SUBSCRIPTION <name> SET */
1554 else if (Matches4("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
1555 COMPLETE_WITH_LIST2("(", "PUBLICATION");
1556 /* ALTER SUBSCRIPTION <name> SET ( */
1557 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "("))
1558 COMPLETE_WITH_LIST2("slot_name", "synchronous_commit");
1559 /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
1560 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "PUBLICATION"))
1562 /* complete with nothing here as this refers to remote publications */
1564 /* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> */
1565 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1566 TailMatches3("SET", "PUBLICATION", MatchAny))
1567 COMPLETE_WITH_CONST("WITH (");
1568 /* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> WITH ( */
1569 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1570 TailMatches5("SET", "PUBLICATION", MatchAny, "WITH", "("))
1571 COMPLETE_WITH_LIST2("copy_data", "refresh");
1572 /* ALTER SCHEMA <name> */
1573 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1574 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1576 /* ALTER COLLATION <name> */
1577 else if (Matches3("ALTER", "COLLATION", MatchAny))
1578 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1580 /* ALTER CONVERSION <name> */
1581 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1582 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1584 /* ALTER DATABASE <name> */
1585 else if (Matches3("ALTER", "DATABASE", MatchAny))
1586 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1587 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1588 "CONNECTION LIMIT");
1590 /* ALTER EVENT TRIGGER */
1591 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1592 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1594 /* ALTER EVENT TRIGGER <name> */
1595 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1596 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1598 /* ALTER EVENT TRIGGER <name> ENABLE */
1599 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1600 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1602 /* ALTER EXTENSION <name> */
1603 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1604 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1606 /* ALTER EXTENSION <name> UPDATE */
1607 else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
1609 completion_info_charp = prev2_wd;
1610 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
1613 /* ALTER EXTENSION <name> UPDATE TO */
1614 else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
1616 completion_info_charp = prev3_wd;
1617 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
1621 else if (Matches2("ALTER", "FOREIGN"))
1622 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1624 /* ALTER FOREIGN DATA WRAPPER <name> */
1625 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1626 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1628 /* ALTER FOREIGN TABLE <name> */
1629 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1631 static const char *const list_ALTER_FOREIGN_TABLE[] =
1632 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1633 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1634 "VALIDATE CONSTRAINT", NULL};
1636 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1640 else if (Matches2("ALTER", "INDEX"))
1641 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1642 "UNION SELECT 'ALL IN TABLESPACE'");
1643 /* ALTER INDEX <name> */
1644 else if (Matches3("ALTER", "INDEX", MatchAny))
1645 COMPLETE_WITH_LIST6("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
1646 "RESET", "ATTACH PARTITION");
1647 else if (Matches4("ALTER", "INDEX", MatchAny, "ATTACH"))
1648 COMPLETE_WITH_CONST("PARTITION");
1649 else if (Matches5("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
1650 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
1651 /* ALTER INDEX <name> ALTER COLUMN <colnum> */
1652 else if (Matches6("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
1653 COMPLETE_WITH_CONST("SET STATISTICS");
1654 /* ALTER INDEX <name> SET */
1655 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1656 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1657 /* ALTER INDEX <name> RESET */
1658 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1659 COMPLETE_WITH_CONST("(");
1660 /* ALTER INDEX <foo> SET|RESET ( */
1661 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1662 COMPLETE_WITH_LIST8("fillfactor", "recheck_on_update",
1663 "vacuum_cleanup_index_scale_factor", /* BTREE */
1664 "fastupdate", "gin_pending_list_limit", /* GIN */
1665 "buffering", /* GiST */
1666 "pages_per_range", "autosummarize" /* BRIN */
1668 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1669 COMPLETE_WITH_LIST8("fillfactor =", "recheck_on_update =",
1670 "vacuum_cleanup_index_scale_factor =", /* BTREE */
1671 "fastupdate =", "gin_pending_list_limit =", /* GIN */
1672 "buffering =", /* GiST */
1673 "pages_per_range =", "autosummarize =" /* BRIN */
1676 /* ALTER LANGUAGE <name> */
1677 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1678 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1680 /* ALTER LARGE OBJECT <oid> */
1681 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1682 COMPLETE_WITH_CONST("OWNER TO");
1684 /* ALTER MATERIALIZED VIEW */
1685 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1686 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1687 "UNION SELECT 'ALL IN TABLESPACE'");
1689 /* ALTER USER,ROLE <name> */
1690 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1691 !TailMatches2("USER", "MAPPING"))
1693 static const char *const list_ALTERUSER[] =
1694 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1695 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1696 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1697 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1698 "REPLICATION", "RESET", "SET", "SUPERUSER",
1699 "VALID UNTIL", "WITH", NULL};
1701 COMPLETE_WITH_LIST(list_ALTERUSER);
1704 /* ALTER USER,ROLE <name> WITH */
1705 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1707 /* Similar to the above, but don't complete "WITH" again. */
1708 static const char *const list_ALTERUSER_WITH[] =
1709 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1710 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1711 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1712 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1713 "REPLICATION", "RESET", "SET", "SUPERUSER",
1714 "VALID UNTIL", NULL};
1716 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1719 /* ALTER DEFAULT PRIVILEGES */
1720 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1721 COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
1722 /* ALTER DEFAULT PRIVILEGES FOR */
1723 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1724 COMPLETE_WITH_CONST("ROLE");
1725 /* ALTER DEFAULT PRIVILEGES IN */
1726 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1727 COMPLETE_WITH_CONST("SCHEMA");
1728 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1729 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1731 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
1732 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1733 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1735 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
1736 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1737 else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1739 COMPLETE_WITH_CONST("ROLE");
1740 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
1741 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1742 else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1743 MatchAny, "IN", "SCHEMA", MatchAny) ||
1744 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1745 MatchAny, "FOR", "ROLE|USER", MatchAny))
1746 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1747 /* ALTER DOMAIN <name> */
1748 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1749 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1750 "VALIDATE CONSTRAINT");
1751 /* ALTER DOMAIN <sth> DROP */
1752 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1753 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1754 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1755 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1757 completion_info_charp = prev3_wd;
1758 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1760 /* ALTER DOMAIN <sth> RENAME */
1761 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1762 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1763 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1764 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1765 COMPLETE_WITH_CONST("TO");
1767 /* ALTER DOMAIN <sth> SET */
1768 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1769 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1770 /* ALTER SEQUENCE <name> */
1771 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1773 static const char *const list_ALTERSEQUENCE[] =
1774 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1775 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1777 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1779 /* ALTER SEQUENCE <name> NO */
1780 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1781 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1782 /* ALTER SERVER <name> */
1783 else if (Matches3("ALTER", "SERVER", MatchAny))
1784 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1785 /* ALTER SERVER <name> VERSION <version> */
1786 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1787 COMPLETE_WITH_CONST("OPTIONS");
1788 /* ALTER SYSTEM SET, RESET, RESET ALL */
1789 else if (Matches2("ALTER", "SYSTEM"))
1790 COMPLETE_WITH_LIST2("SET", "RESET");
1791 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1792 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1793 else if (Matches4("ALTER", "SYSTEM", "SET", MatchAny))
1794 COMPLETE_WITH_CONST("TO");
1795 /* ALTER VIEW <name> */
1796 else if (Matches3("ALTER", "VIEW", MatchAny))
1797 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1799 /* ALTER MATERIALIZED VIEW <name> */
1800 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1801 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1804 /* ALTER POLICY <name> */
1805 else if (Matches2("ALTER", "POLICY"))
1806 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1807 /* ALTER POLICY <name> ON */
1808 else if (Matches3("ALTER", "POLICY", MatchAny))
1809 COMPLETE_WITH_CONST("ON");
1810 /* ALTER POLICY <name> ON <table> */
1811 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1813 completion_info_charp = prev2_wd;
1814 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1816 /* ALTER POLICY <name> ON <table> - show options */
1817 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1818 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1819 /* ALTER POLICY <name> ON <table> TO <role> */
1820 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1821 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1822 /* ALTER POLICY <name> ON <table> USING ( */
1823 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1824 COMPLETE_WITH_CONST("(");
1825 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1826 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1827 COMPLETE_WITH_CONST("(");
1829 /* ALTER RULE <name>, add ON */
1830 else if (Matches3("ALTER", "RULE", MatchAny))
1831 COMPLETE_WITH_CONST("ON");
1833 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1834 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1836 completion_info_charp = prev2_wd;
1837 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1840 /* ALTER RULE <name> ON <name> */
1841 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1842 COMPLETE_WITH_CONST("RENAME TO");
1844 /* ALTER STATISTICS <name> */
1845 else if (Matches3("ALTER", "STATISTICS", MatchAny))
1846 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1848 /* ALTER TRIGGER <name>, add ON */
1849 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1850 COMPLETE_WITH_CONST("ON");
1852 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1854 completion_info_charp = prev2_wd;
1855 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1859 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1861 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1862 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1864 /* ALTER TRIGGER <name> ON <name> */
1865 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1866 COMPLETE_WITH_CONST("RENAME TO");
1869 * If we detect ALTER TABLE <name>, suggest sub commands
1871 else if (Matches3("ALTER", "TABLE", MatchAny))
1873 static const char *const list_ALTER2[] =
1874 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1875 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1876 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", "ATTACH PARTITION",
1877 "DETACH PARTITION", NULL};
1879 COMPLETE_WITH_LIST(list_ALTER2);
1881 /* ALTER TABLE xxx ENABLE */
1882 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1883 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1885 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1886 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1887 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1889 completion_info_charp = prev3_wd;
1890 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1892 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1894 completion_info_charp = prev4_wd;
1895 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1897 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1899 completion_info_charp = prev3_wd;
1900 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1902 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1904 completion_info_charp = prev4_wd;
1905 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1907 /* ALTER TABLE xxx INHERIT */
1908 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1909 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1910 /* ALTER TABLE xxx NO INHERIT */
1911 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1912 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1913 /* ALTER TABLE xxx DISABLE */
1914 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1915 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1916 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1918 completion_info_charp = prev3_wd;
1919 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1921 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1923 completion_info_charp = prev3_wd;
1924 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1927 /* ALTER TABLE xxx ALTER */
1928 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1929 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1931 /* ALTER TABLE xxx RENAME */
1932 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1933 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1934 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1935 COMPLETE_WITH_ATTR(prev3_wd, "");
1937 /* ALTER TABLE xxx RENAME yyy */
1938 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1939 COMPLETE_WITH_CONST("TO");
1941 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1942 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1943 COMPLETE_WITH_CONST("TO");
1945 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1946 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1947 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1948 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1949 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1950 COMPLETE_WITH_ATTR(prev3_wd, "");
1953 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1954 * provide list of constraints
1956 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1958 completion_info_charp = prev3_wd;
1959 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1961 /* ALTER TABLE ALTER [COLUMN] <foo> */
1962 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1963 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1964 COMPLETE_WITH_LIST6("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
1965 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1966 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1967 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1968 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1969 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1970 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1971 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1972 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1973 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1974 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1975 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1976 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1977 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1978 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1979 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1980 COMPLETE_WITH_LIST3("DEFAULT", "IDENTITY", "NOT NULL");
1981 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1982 COMPLETE_WITH_CONST("ON");
1983 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1985 completion_info_charp = prev3_wd;
1986 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1988 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1989 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1990 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1994 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1997 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1998 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1999 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
2000 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
2001 COMPLETE_WITH_CONST("OIDS");
2002 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
2003 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
2004 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
2005 /* ALTER TABLE <foo> RESET */
2006 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
2007 COMPLETE_WITH_CONST("(");
2008 /* ALTER TABLE <foo> SET|RESET ( */
2009 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
2011 static const char *const list_TABLEOPTIONS[] =
2013 "autovacuum_analyze_scale_factor",
2014 "autovacuum_analyze_threshold",
2015 "autovacuum_enabled",
2016 "autovacuum_freeze_max_age",
2017 "autovacuum_freeze_min_age",
2018 "autovacuum_freeze_table_age",
2019 "autovacuum_multixact_freeze_max_age",
2020 "autovacuum_multixact_freeze_min_age",
2021 "autovacuum_multixact_freeze_table_age",
2022 "autovacuum_vacuum_cost_delay",
2023 "autovacuum_vacuum_cost_limit",
2024 "autovacuum_vacuum_scale_factor",
2025 "autovacuum_vacuum_threshold",
2028 "log_autovacuum_min_duration",
2029 "toast.autovacuum_enabled",
2030 "toast.autovacuum_freeze_max_age",
2031 "toast.autovacuum_freeze_min_age",
2032 "toast.autovacuum_freeze_table_age",
2033 "toast.autovacuum_multixact_freeze_max_age",
2034 "toast.autovacuum_multixact_freeze_min_age",
2035 "toast.autovacuum_multixact_freeze_table_age",
2036 "toast.autovacuum_vacuum_cost_delay",
2037 "toast.autovacuum_vacuum_cost_limit",
2038 "toast.autovacuum_vacuum_scale_factor",
2039 "toast.autovacuum_vacuum_threshold",
2040 "toast.log_autovacuum_min_duration",
2041 "user_catalog_table",
2045 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
2047 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
2049 completion_info_charp = prev5_wd;
2050 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2052 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
2053 COMPLETE_WITH_CONST("INDEX");
2054 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
2055 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
2056 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
2057 COMPLETE_WITH_CONST("IDENTITY");
2060 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
2063 else if (Matches5("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
2064 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2065 /* Limited completion support for partition bound specification */
2066 else if (TailMatches3("ATTACH", "PARTITION", MatchAny))
2067 COMPLETE_WITH_LIST2("FOR VALUES", "DEFAULT");
2068 else if (TailMatches2("FOR", "VALUES"))
2069 COMPLETE_WITH_LIST3("FROM (", "IN (", "WITH (");
2072 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
2073 * partitions of <foo>.
2075 else if (Matches5("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
2077 completion_info_charp = prev3_wd;
2078 COMPLETE_WITH_QUERY(Query_for_partition_of_table);
2081 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
2082 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
2083 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
2084 /* ALTER TABLESPACE <foo> SET|RESET */
2085 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
2086 COMPLETE_WITH_CONST("(");
2087 /* ALTER TABLESPACE <foo> SET|RESET ( */
2088 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
2089 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
2090 "effective_io_concurrency");
2092 /* ALTER TEXT SEARCH */
2093 else if (Matches3("ALTER", "TEXT", "SEARCH"))
2094 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2095 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
2096 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
2097 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
2098 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
2099 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2100 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
2102 "OWNER TO", "RENAME TO", "SET SCHEMA");
2104 /* complete ALTER TYPE <foo> with actions */
2105 else if (Matches3("ALTER", "TYPE", MatchAny))
2106 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
2108 "OWNER TO", "RENAME", "SET SCHEMA");
2109 /* complete ALTER TYPE <foo> ADD with actions */
2110 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
2111 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
2112 /* ALTER TYPE <foo> RENAME */
2113 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
2114 COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
2115 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
2116 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
2117 COMPLETE_WITH_CONST("TO");
2120 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
2123 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
2124 COMPLETE_WITH_ATTR(prev3_wd, "");
2125 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
2126 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
2127 COMPLETE_WITH_CONST("TYPE");
2128 /* complete ALTER GROUP <foo> */
2129 else if (Matches3("ALTER", "GROUP", MatchAny))
2130 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
2131 /* complete ALTER GROUP <foo> ADD|DROP with USER */
2132 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
2133 COMPLETE_WITH_CONST("USER");
2134 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
2135 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
2136 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2139 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
2141 else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
2142 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
2145 else if (Matches1("BEGIN"))
2146 COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2148 else if (Matches1("END|ABORT"))
2149 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
2151 else if (Matches1("COMMIT"))
2152 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
2153 /* RELEASE SAVEPOINT */
2154 else if (Matches1("RELEASE"))
2155 COMPLETE_WITH_CONST("SAVEPOINT");
2157 else if (Matches1("ROLLBACK"))
2158 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
2160 else if (Matches1("CALL"))
2161 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures, NULL);
2162 else if (Matches2("CALL", MatchAny))
2163 COMPLETE_WITH_CONST("(");
2165 else if (Matches1("CLUSTER"))
2166 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
2167 else if (Matches2("CLUSTER", "VERBOSE"))
2168 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2169 /* If we have CLUSTER <sth>, then add "USING" */
2170 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
2171 COMPLETE_WITH_CONST("USING");
2172 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
2173 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
2174 COMPLETE_WITH_CONST("USING");
2175 /* If we have CLUSTER <sth> USING, then add the index as well */
2176 else if (Matches3("CLUSTER", MatchAny, "USING") ||
2177 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
2179 completion_info_charp = prev2_wd;
2180 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2184 else if (Matches1("COMMENT"))
2185 COMPLETE_WITH_CONST("ON");
2186 else if (Matches2("COMMENT", "ON"))
2188 static const char *const list_COMMENT[] =
2189 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
2190 "EVENT TRIGGER", "EXTENSION",
2191 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2192 "SERVER", "INDEX", "LANGUAGE", "POLICY", "PUBLICATION", "RULE",
2193 "SCHEMA", "SEQUENCE", "STATISTICS", "SUBSCRIPTION",
2194 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
2195 "PROCEDURE", "ROUTINE",
2196 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
2197 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
2199 COMPLETE_WITH_LIST(list_COMMENT);
2201 else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
2202 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2203 else if (Matches3("COMMENT", "ON", "FOREIGN"))
2204 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2205 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
2206 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2207 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
2208 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
2209 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
2210 COMPLETE_WITH_CONST("ON");
2211 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2213 completion_info_charp = prev2_wd;
2214 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
2216 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
2217 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2218 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
2219 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2220 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
2221 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2222 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
2223 COMPLETE_WITH_CONST("IS");
2228 * If we have COPY, offer list of tables or "(" (Also cover the analogous
2229 * backslash command).
2231 else if (Matches1("COPY|\\copy"))
2232 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2233 " UNION ALL SELECT '('");
2234 /* If we have COPY BINARY, complete with list of tables */
2235 else if (Matches2("COPY", "BINARY"))
2236 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2237 /* If we have COPY (, complete it with legal commands */
2238 else if (Matches2("COPY|\\copy", "("))
2239 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
2240 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
2241 else if (Matches2("COPY|\\copy", MatchAny) ||
2242 Matches3("COPY", "BINARY", MatchAny))
2243 COMPLETE_WITH_LIST2("FROM", "TO");
2244 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
2245 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
2246 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
2248 completion_charp = "";
2249 matches = completion_matches(text, complete_from_files);
2252 /* Handle COPY [BINARY] <sth> FROM|TO filename */
2253 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
2254 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
2255 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
2258 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
2259 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
2260 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
2261 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
2264 /* CREATE ACCESS METHOD */
2265 /* Complete "CREATE ACCESS METHOD <name>" */
2266 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
2267 COMPLETE_WITH_CONST("TYPE");
2268 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
2269 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
2270 COMPLETE_WITH_CONST("INDEX");
2271 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
2272 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
2273 COMPLETE_WITH_CONST("HANDLER");
2275 /* CREATE DATABASE */
2276 else if (Matches3("CREATE", "DATABASE", MatchAny))
2277 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2279 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2280 "LC_COLLATE", "LC_CTYPE");
2282 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2283 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2285 /* CREATE EXTENSION */
2286 /* Complete with available extensions rather than installed ones. */
2287 else if (Matches2("CREATE", "EXTENSION"))
2288 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2289 /* CREATE EXTENSION <name> */
2290 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2291 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2292 /* CREATE EXTENSION <name> VERSION */
2293 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2295 completion_info_charp = prev2_wd;
2296 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2299 /* CREATE FOREIGN */
2300 else if (Matches2("CREATE", "FOREIGN"))
2301 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2303 /* CREATE FOREIGN DATA WRAPPER */
2304 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2305 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2307 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2308 /* First off we complete CREATE UNIQUE with "INDEX" */
2309 else if (TailMatches2("CREATE", "UNIQUE"))
2310 COMPLETE_WITH_CONST("INDEX");
2313 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2316 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2317 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2318 " UNION SELECT 'ON'"
2319 " UNION SELECT 'CONCURRENTLY'");
2322 * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
2323 * that can indexes can be created on
2325 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2326 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2327 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tpm, NULL);
2330 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2333 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2334 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2335 " UNION SELECT 'ON'");
2336 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2337 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2338 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2339 COMPLETE_WITH_CONST("ON");
2342 * Complete INDEX <name> ON <table> with a list of table columns (which
2343 * should really be in parens)
2345 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2346 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2347 COMPLETE_WITH_LIST2("(", "USING");
2348 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2349 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2350 COMPLETE_WITH_ATTR(prev2_wd, "");
2351 /* same if you put in USING */
2352 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2353 COMPLETE_WITH_ATTR(prev4_wd, "");
2354 /* Complete USING with an index method */
2355 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2356 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2357 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2358 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2359 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2360 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2361 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2362 COMPLETE_WITH_CONST("(");
2365 /* Complete "CREATE POLICY <name> ON" */
2366 else if (Matches3("CREATE", "POLICY", MatchAny))
2367 COMPLETE_WITH_CONST("ON");
2368 /* Complete "CREATE POLICY <name> ON <table>" */
2369 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2370 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2371 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
2372 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2373 COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
2374 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
2375 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
2376 COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
2379 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2380 * FOR|TO|USING|WITH CHECK
2382 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
2383 COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
2384 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2385 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2386 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2387 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2388 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2389 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2390 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2391 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2392 COMPLETE_WITH_LIST2("TO", "USING (");
2393 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2394 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2395 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2396 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2397 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2398 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2399 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2400 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2401 COMPLETE_WITH_CONST("(");
2404 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2405 * ALL|SELECT|INSERT|UPDATE|DELETE
2407 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
2408 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2411 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2412 * INSERT TO|WITH CHECK"
2414 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
2415 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2418 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2419 * SELECT|DELETE TO|USING"
2421 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
2422 COMPLETE_WITH_LIST2("TO", "USING (");
2425 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2426 * ALL|UPDATE TO|USING|WITH CHECK
2428 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
2429 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2432 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
2435 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
2436 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2439 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2442 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
2443 COMPLETE_WITH_CONST("(");
2446 /* CREATE PUBLICATION */
2447 else if (Matches3("CREATE", "PUBLICATION", MatchAny))
2448 COMPLETE_WITH_LIST3("FOR TABLE", "FOR ALL TABLES", "WITH (");
2449 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR"))
2450 COMPLETE_WITH_LIST2("TABLE", "ALL TABLES");
2451 /* Complete "CREATE PUBLICATION <name> FOR TABLE <table>" */
2452 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
2453 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2454 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
2455 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
2456 COMPLETE_WITH_CONST("publish");
2459 /* Complete "CREATE RULE <sth>" with "AS ON" */
2460 else if (Matches3("CREATE", "RULE", MatchAny))
2461 COMPLETE_WITH_CONST("AS ON");
2462 /* Complete "CREATE RULE <sth> AS" with "ON" */
2463 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2464 COMPLETE_WITH_CONST("ON");
2465 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2466 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2467 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2468 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2469 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2470 COMPLETE_WITH_CONST("TO");
2471 /* Complete "AS ON <sth> TO" with a table name */
2472 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2473 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2475 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2476 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2477 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2478 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2479 "CYCLE", "OWNED BY", "START WITH");
2480 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2481 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2482 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2484 /* CREATE SERVER <name> */
2485 else if (Matches3("CREATE", "SERVER", MatchAny))
2486 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2488 /* CREATE STATISTICS <name> */
2489 else if (Matches3("CREATE", "STATISTICS", MatchAny))
2490 COMPLETE_WITH_LIST2("(", "ON");
2491 else if (Matches4("CREATE", "STATISTICS", MatchAny, "("))
2492 COMPLETE_WITH_LIST2("ndistinct", "dependencies");
2493 else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
2494 previous_words[0][0] == '(' &&
2495 previous_words[0][strlen(previous_words[0]) - 1] == ')')
2496 COMPLETE_WITH_CONST("ON");
2497 else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
2498 TailMatches1("FROM"))
2499 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2501 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2502 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2503 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2504 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2505 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2506 else if (TailMatches2("CREATE", "UNLOGGED"))
2507 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2508 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
2509 else if (TailMatches2("PARTITION", "BY"))
2510 COMPLETE_WITH_LIST2("RANGE (", "LIST (");
2511 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
2512 else if (TailMatches2("PARTITION", "OF"))
2513 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables, "");
2514 /* Limited completion support for partition bound specification */
2515 else if (TailMatches3("PARTITION", "OF", MatchAny))
2516 COMPLETE_WITH_LIST2("FOR VALUES", "DEFAULT");
2518 /* CREATE TABLESPACE */
2519 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2520 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2521 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2522 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2523 COMPLETE_WITH_CONST("LOCATION");
2525 /* CREATE TEXT SEARCH */
2526 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2527 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2528 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2529 COMPLETE_WITH_CONST("(");
2531 /* CREATE SUBSCRIPTION */
2532 else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
2533 COMPLETE_WITH_CONST("CONNECTION");
2534 else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
2535 COMPLETE_WITH_CONST("PUBLICATION");
2536 else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
2537 MatchAny, "PUBLICATION"))
2539 /* complete with nothing here as this refers to remote publications */
2541 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("PUBLICATION", MatchAny))
2542 COMPLETE_WITH_CONST("WITH (");
2543 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
2544 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
2545 COMPLETE_WITH_LIST6("copy_data", "connect", "create_slot", "enabled",
2546 "slot_name", "synchronous_commit");
2548 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2549 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2550 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2551 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2552 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2553 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2554 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2555 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2556 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2557 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2558 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2559 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2560 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2561 COMPLETE_WITH_LIST2("ON", "OR");
2564 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2567 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2568 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2569 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2570 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2571 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2572 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
2573 COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
2574 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2575 else if (HeadMatches2("CREATE", "TRIGGER") &&
2576 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
2577 COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2578 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
2579 COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
2580 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
2581 COMPLETE_WITH_CONST("AS");
2582 else if (HeadMatches2("CREATE", "TRIGGER") &&
2583 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
2584 TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
2585 COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2586 else if (HeadMatches2("CREATE", "TRIGGER") &&
2587 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
2588 TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
2589 COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2590 else if (HeadMatches2("CREATE", "TRIGGER") &&
2591 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2592 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2593 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
2594 TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
2595 COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
2596 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
2597 COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
2598 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
2599 COMPLETE_WITH_LIST2("ROW", "STATEMENT");
2600 else if (HeadMatches2("CREATE", "TRIGGER") &&
2601 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
2602 TailMatches2("FOR", "ROW|STATEMENT")))
2603 COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
2604 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2605 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2606 COMPLETE_WITH_CONST("PROCEDURE");
2607 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
2608 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2610 /* CREATE ROLE,USER,GROUP <name> */
2611 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2612 !TailMatches2("USER", "MAPPING"))
2614 static const char *const list_CREATEROLE[] =
2615 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2616 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2617 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2618 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2619 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2620 "VALID UNTIL", "WITH", NULL};
2622 COMPLETE_WITH_LIST(list_CREATEROLE);
2625 /* CREATE ROLE,USER,GROUP <name> WITH */
2626 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2628 /* Similar to the above, but don't complete "WITH" again. */
2629 static const char *const list_CREATEROLE_WITH[] =
2630 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2631 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2632 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2633 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2634 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2635 "VALID UNTIL", NULL};
2637 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2640 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2641 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2642 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2644 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2645 /* Complete CREATE VIEW <name> with AS */
2646 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2647 COMPLETE_WITH_CONST("AS");
2648 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2649 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2650 COMPLETE_WITH_CONST("SELECT");
2652 /* CREATE MATERIALIZED VIEW */
2653 else if (Matches2("CREATE", "MATERIALIZED"))
2654 COMPLETE_WITH_CONST("VIEW");
2655 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2656 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2657 COMPLETE_WITH_CONST("AS");
2658 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2659 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2660 COMPLETE_WITH_CONST("SELECT");
2662 /* CREATE EVENT TRIGGER */
2663 else if (Matches2("CREATE", "EVENT"))
2664 COMPLETE_WITH_CONST("TRIGGER");
2665 /* Complete CREATE EVENT TRIGGER <name> with ON */
2666 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2667 COMPLETE_WITH_CONST("ON");
2668 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2669 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2670 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2673 else if (Matches1("DEALLOCATE"))
2674 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2677 else if (Matches2("DECLARE", MatchAny))
2678 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2680 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2681 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2683 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2684 /* ... despite which, only complete DELETE with FROM at start of line */
2685 else if (Matches1("DELETE"))
2686 COMPLETE_WITH_CONST("FROM");
2687 /* Complete DELETE FROM with a list of tables */
2688 else if (TailMatches2("DELETE", "FROM"))
2689 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2690 /* Complete DELETE FROM <table> */
2691 else if (TailMatches3("DELETE", "FROM", MatchAny))
2692 COMPLETE_WITH_LIST2("USING", "WHERE");
2693 /* XXX: implement tab completion for DELETE ... USING */
2696 else if (Matches1("DISCARD"))
2697 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2700 else if (Matches1("DO"))
2701 COMPLETE_WITH_CONST("LANGUAGE");
2704 /* Complete DROP object with CASCADE / RESTRICT */
2705 else if (Matches3("DROP",
2706 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
2708 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2709 (Matches4("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
2710 ends_with(prev_wd, ')')) ||
2711 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2712 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2713 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2714 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2715 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2717 /* help completing some of the variants */
2718 else if (Matches3("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
2719 COMPLETE_WITH_CONST("(");
2720 else if (Matches4("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
2721 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2722 else if (Matches2("DROP", "FOREIGN"))
2723 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2726 else if (Matches2("DROP", "INDEX"))
2727 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2728 " UNION SELECT 'CONCURRENTLY'");
2729 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2730 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2731 else if (Matches3("DROP", "INDEX", MatchAny))
2732 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2733 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2734 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2736 /* DROP MATERIALIZED VIEW */
2737 else if (Matches2("DROP", "MATERIALIZED"))
2738 COMPLETE_WITH_CONST("VIEW");
2739 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2740 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2743 else if (Matches2("DROP", "OWNED"))
2744 COMPLETE_WITH_CONST("BY");
2745 else if (Matches3("DROP", "OWNED", "BY"))
2746 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2748 /* DROP TEXT SEARCH */
2749 else if (Matches3("DROP", "TEXT", "SEARCH"))
2750 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2753 else if (Matches3("DROP", "TRIGGER", MatchAny))
2754 COMPLETE_WITH_CONST("ON");
2755 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2757 completion_info_charp = prev2_wd;
2758 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2760 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2761 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2763 /* DROP ACCESS METHOD */
2764 else if (Matches2("DROP", "ACCESS"))
2765 COMPLETE_WITH_CONST("METHOD");
2766 else if (Matches3("DROP", "ACCESS", "METHOD"))
2767 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2769 /* DROP EVENT TRIGGER */
2770 else if (Matches2("DROP", "EVENT"))
2771 COMPLETE_WITH_CONST("TRIGGER");
2772 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2773 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2775 /* DROP POLICY <name> */
2776 else if (Matches2("DROP", "POLICY"))
2777 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2778 /* DROP POLICY <name> ON */
2779 else if (Matches3("DROP", "POLICY", MatchAny))
2780 COMPLETE_WITH_CONST("ON");
2781 /* DROP POLICY <name> ON <table> */
2782 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2784 completion_info_charp = prev2_wd;
2785 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2789 else if (Matches3("DROP", "RULE", MatchAny))
2790 COMPLETE_WITH_CONST("ON");
2791 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2793 completion_info_charp = prev2_wd;
2794 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2796 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2797 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2800 else if (Matches1("EXECUTE"))
2801 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2806 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2808 else if (Matches1("EXPLAIN"))
2809 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2810 "ANALYZE", "VERBOSE");
2811 else if (Matches2("EXPLAIN", "ANALYZE"))
2812 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2814 else if (Matches2("EXPLAIN", "VERBOSE") ||
2815 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2816 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2819 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2820 else if (Matches1("FETCH|MOVE"))
2821 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2822 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2823 else if (Matches2("FETCH|MOVE", MatchAny))
2824 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2827 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2828 * but we may as well tab-complete both: perhaps some users prefer one
2829 * variant or the other.
2831 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2832 COMPLETE_WITH_LIST2("FROM", "IN");
2834 /* FOREIGN DATA WRAPPER */
2835 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2836 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2837 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2838 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2839 /* applies in CREATE SERVER */
2840 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2841 HeadMatches2("CREATE", "SERVER"))
2842 COMPLETE_WITH_CONST("OPTIONS");
2845 else if (TailMatches2("FOREIGN", "TABLE") &&
2846 !TailMatches3("CREATE", MatchAny, MatchAny))
2847 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2849 /* FOREIGN SERVER */
2850 else if (TailMatches2("FOREIGN", "SERVER"))
2851 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2854 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
2855 * ALTER DEFAULT PRIVILEGES, so use TailMatches
2857 /* Complete GRANT/REVOKE with a list of roles and privileges */
2858 else if (TailMatches1("GRANT|REVOKE"))
2861 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
2862 * privileges (can't grant roles)
2864 if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
2865 COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
2866 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
2867 "EXECUTE", "USAGE", "ALL");
2869 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2870 " UNION SELECT 'SELECT'"
2871 " UNION SELECT 'INSERT'"
2872 " UNION SELECT 'UPDATE'"
2873 " UNION SELECT 'DELETE'"
2874 " UNION SELECT 'TRUNCATE'"
2875 " UNION SELECT 'REFERENCES'"
2876 " UNION SELECT 'TRIGGER'"
2877 " UNION SELECT 'CREATE'"
2878 " UNION SELECT 'CONNECT'"
2879 " UNION SELECT 'TEMPORARY'"
2880 " UNION SELECT 'EXECUTE'"
2881 " UNION SELECT 'USAGE'"
2882 " UNION SELECT 'ALL'");
2886 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2889 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2891 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2892 COMPLETE_WITH_CONST("ON");
2893 else if (TailMatches2("GRANT", MatchAny))
2894 COMPLETE_WITH_CONST("TO");
2896 COMPLETE_WITH_CONST("FROM");
2900 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2903 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2904 * result via UNION; seems to work intuitively.
2906 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2907 * here will only work if the privilege list contains exactly one
2910 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2913 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
2914 * objects supported.
2916 if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
2917 COMPLETE_WITH_LIST7("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS");
2919 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2920 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2921 " UNION SELECT 'ALL PROCEDURES IN SCHEMA'"
2922 " UNION SELECT 'ALL ROUTINES IN SCHEMA'"
2923 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2924 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2925 " UNION SELECT 'DATABASE'"
2926 " UNION SELECT 'DOMAIN'"
2927 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2928 " UNION SELECT 'FOREIGN SERVER'"
2929 " UNION SELECT 'FUNCTION'"
2930 " UNION SELECT 'LANGUAGE'"
2931 " UNION SELECT 'LARGE OBJECT'"
2932 " UNION SELECT 'PROCEDURE'"
2933 " UNION SELECT 'ROUTINE'"
2934 " UNION SELECT 'SCHEMA'"
2935 " UNION SELECT 'SEQUENCE'"
2936 " UNION SELECT 'TABLE'"
2937 " UNION SELECT 'TABLESPACE'"
2938 " UNION SELECT 'TYPE'");
2940 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2941 COMPLETE_WITH_LIST5("FUNCTIONS IN SCHEMA",
2942 "PROCEDURES IN SCHEMA",
2943 "ROUTINES IN SCHEMA",
2944 "SEQUENCES IN SCHEMA",
2945 "TABLES IN SCHEMA");
2946 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2947 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2950 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2951 * appropriate objects.
2953 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2955 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2957 if (TailMatches1("DATABASE"))
2958 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2959 else if (TailMatches1("DOMAIN"))
2960 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2961 else if (TailMatches1("FUNCTION"))
2962 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2963 else if (TailMatches1("LANGUAGE"))
2964 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2965 else if (TailMatches1("PROCEDURE"))
2966 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures, NULL);
2967 else if (TailMatches1("ROUTINE"))
2968 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
2969 else if (TailMatches1("SCHEMA"))
2970 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2971 else if (TailMatches1("SEQUENCE"))
2972 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2973 else if (TailMatches1("TABLE"))
2974 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2975 else if (TailMatches1("TABLESPACE"))
2976 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2977 else if (TailMatches1("TYPE"))
2978 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2979 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2980 COMPLETE_WITH_CONST("TO");
2982 COMPLETE_WITH_CONST("FROM");
2986 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2987 * CURRENT_USER, or SESSION_USER.
2989 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2990 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2991 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2992 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
2993 else if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
2994 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2995 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2996 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2997 COMPLETE_WITH_CONST("TO");
2998 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2999 COMPLETE_WITH_CONST("FROM");
3001 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
3002 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
3004 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3005 COMPLETE_WITH_CONST("TO");
3007 COMPLETE_WITH_CONST("FROM");
3010 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
3011 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
3013 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3014 COMPLETE_WITH_CONST("TO");
3016 COMPLETE_WITH_CONST("FROM");
3019 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
3020 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
3022 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3023 COMPLETE_WITH_CONST("TO");
3025 COMPLETE_WITH_CONST("FROM");
3029 else if (TailMatches3("FROM", MatchAny, "GROUP"))
3030 COMPLETE_WITH_CONST("BY");
3032 /* IMPORT FOREIGN SCHEMA */
3033 else if (Matches1("IMPORT"))
3034 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
3035 else if (Matches2("IMPORT", "FOREIGN"))
3036 COMPLETE_WITH_CONST("SCHEMA");
3038 /* INSERT --- can be inside EXPLAIN, RULE, etc */
3039 /* Complete INSERT with "INTO" */
3040 else if (TailMatches1("INSERT"))
3041 COMPLETE_WITH_CONST("INTO");
3042 /* Complete INSERT INTO with table names */
3043 else if (TailMatches2("INSERT", "INTO"))
3044 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3045 /* Complete "INSERT INTO <table> (" with attribute names */
3046 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
3047 COMPLETE_WITH_ATTR(prev2_wd, "");
3050 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
3051 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
3053 else if (TailMatches3("INSERT", "INTO", MatchAny))
3054 COMPLETE_WITH_LIST6("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
3057 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
3058 * "TABLE" or "OVERRIDING"
3060 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
3061 ends_with(prev_wd, ')'))
3062 COMPLETE_WITH_LIST4("SELECT", "TABLE", "VALUES", "OVERRIDING");
3064 /* Complete OVERRIDING */
3065 else if (TailMatches1("OVERRIDING"))
3066 COMPLETE_WITH_LIST2("SYSTEM VALUE", "USER VALUE");
3068 /* Complete after OVERRIDING clause */
3069 else if (TailMatches3("OVERRIDING", MatchAny, "VALUE"))
3070 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
3072 /* Insert an open parenthesis after "VALUES" */
3073 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
3074 COMPLETE_WITH_CONST("(");
3077 /* Complete LOCK [TABLE] with a list of tables */
3078 else if (Matches1("LOCK"))
3079 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
3080 " UNION SELECT 'TABLE'");
3081 else if (Matches2("LOCK", "TABLE"))
3082 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
3084 /* For the following, handle the case of a single table only for now */
3086 /* Complete LOCK [TABLE] <table> with "IN" */
3087 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
3088 Matches3("LOCK", "TABLE", MatchAny))
3089 COMPLETE_WITH_CONST("IN");
3091 /* Complete LOCK [TABLE] <table> IN with a lock mode */
3092 else if (Matches3("LOCK", MatchAny, "IN") ||
3093 Matches4("LOCK", "TABLE", MatchAny, "IN"))
3094 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
3095 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
3096 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
3097 "SHARE ROW EXCLUSIVE MODE",
3098 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
3100 /* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
3101 else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
3102 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
3103 COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
3105 /* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
3106 else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
3107 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
3108 COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
3109 "UPDATE EXCLUSIVE MODE");
3111 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
3112 else if (TailMatches1("NOTIFY"))
3113 COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s'");
3116 else if (TailMatches1("OPTIONS"))
3117 COMPLETE_WITH_CONST("(");
3119 /* OWNER TO - complete with available roles */
3120 else if (TailMatches2("OWNER", "TO"))
3121 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3124 else if (TailMatches3("FROM", MatchAny, "ORDER"))
3125 COMPLETE_WITH_CONST("BY");
3126 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
3127 COMPLETE_WITH_ATTR(prev3_wd, "");
3130 else if (Matches3("PREPARE", MatchAny, "AS"))
3131 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
3134 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
3135 * managers, not for manual use in interactive sessions.
3138 /* REASSIGN OWNED BY xxx TO yyy */
3139 else if (Matches1("REASSIGN"))
3140 COMPLETE_WITH_CONST("OWNED BY");
3141 else if (Matches2("REASSIGN", "OWNED"))
3142 COMPLETE_WITH_CONST("BY");
3143 else if (Matches3("REASSIGN", "OWNED", "BY"))
3144 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3145 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
3146 COMPLETE_WITH_CONST("TO");
3147 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
3148 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3150 /* REFRESH MATERIALIZED VIEW */
3151 else if (Matches1("REFRESH"))
3152 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
3153 else if (Matches2("REFRESH", "MATERIALIZED"))
3154 COMPLETE_WITH_CONST("VIEW");
3155 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
3156 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
3157 " UNION SELECT 'CONCURRENTLY'");
3158 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
3159 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3160 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
3161 COMPLETE_WITH_CONST("WITH");
3162 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
3163 COMPLETE_WITH_CONST("WITH");
3164 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
3165 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3166 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
3167 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3168 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
3169 COMPLETE_WITH_CONST("DATA");
3170 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
3171 COMPLETE_WITH_CONST("DATA");
3174 else if (Matches1("REINDEX"))
3175 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
3176 else if (Matches2("REINDEX", "TABLE"))
3177 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3178 else if (Matches2("REINDEX", "INDEX"))
3179 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3180 else if (Matches2("REINDEX", "SCHEMA"))
3181 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3182 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
3183 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3185 /* SECURITY LABEL */
3186 else if (Matches1("SECURITY"))
3187 COMPLETE_WITH_CONST("LABEL");
3188 else if (Matches2("SECURITY", "LABEL"))
3189 COMPLETE_WITH_LIST2("ON", "FOR");
3190 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
3191 COMPLETE_WITH_CONST("ON");
3192 else if (Matches3("SECURITY", "LABEL", "ON") ||
3193 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
3195 static const char *const list_SECURITY_LABEL[] =
3196 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
3197 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
3198 "MATERIALIZED VIEW", "LANGUAGE", "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
3199 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW", NULL};
3201 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
3203 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
3204 COMPLETE_WITH_CONST("IS");
3209 /* SET, RESET, SHOW */
3210 /* Complete with a variable name */
3211 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
3212 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
3213 else if (Matches1("SHOW"))
3214 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
3215 /* Complete "SET TRANSACTION" */
3216 else if (Matches2("SET", "TRANSACTION"))
3217 COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3218 else if (Matches2("BEGIN|START", "TRANSACTION") ||
3219 Matches2("BEGIN", "WORK") ||
3220 Matches1("BEGIN") ||
3221 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
3222 COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3223 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
3224 Matches2("BEGIN", "NOT") ||
3225 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
3226 COMPLETE_WITH_CONST("DEFERRABLE");
3227 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
3228 Matches2("BEGIN", "ISOLATION") ||
3229 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
3230 COMPLETE_WITH_CONST("LEVEL");
3231 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
3232 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
3233 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
3234 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
3235 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
3236 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
3237 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
3238 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
3239 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
3240 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
3241 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
3242 COMPLETE_WITH_CONST("READ");
3243 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
3244 Matches2("BEGIN", "READ") ||
3245 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
3246 COMPLETE_WITH_LIST2("ONLY", "WRITE");
3247 /* SET CONSTRAINTS */
3248 else if (Matches2("SET", "CONSTRAINTS"))
3249 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
3250 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
3251 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
3252 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
3253 /* Complete SET ROLE */
3254 else if (Matches2("SET", "ROLE"))
3255 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3256 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
3257 else if (Matches2("SET", "SESSION"))
3258 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
3259 /* Complete SET SESSION AUTHORIZATION with username */
3260 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
3261 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
3262 /* Complete RESET SESSION with AUTHORIZATION */
3263 else if (Matches2("RESET", "SESSION"))
3264 COMPLETE_WITH_CONST("AUTHORIZATION");
3265 /* Complete SET <var> with "TO" */
3266 else if (Matches2("SET", MatchAny))
3267 COMPLETE_WITH_CONST("TO");
3270 * Complete ALTER DATABASE|FUNCTION||PROCEDURE|ROLE|ROUTINE|USER ... SET
3273 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER") &&
3274 TailMatches2("SET", MatchAny))
3275 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
3276 /* Suggest possible variable values */
3277 else if (TailMatches3("SET", MatchAny, "TO|="))
3279 /* special cased code for individual GUCs */
3280 if (TailMatches2("DateStyle", "TO|="))
3282 static const char *const my_list[] =
3283 {"ISO", "SQL", "Postgres", "German",
3284 "YMD", "DMY", "MDY",
3285 "US", "European", "NonEuropean",
3288 COMPLETE_WITH_LIST(my_list);
3290 else if (TailMatches2("search_path", "TO|="))
3291 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
3292 " AND nspname not like 'pg\\_toast%%' "
3293 " AND nspname not like 'pg\\_temp%%' "
3294 " UNION SELECT 'DEFAULT' ");
3297 /* generic, type based, GUC support */
3298 char *guctype = get_guctype(prev2_wd);
3300 if (guctype && strcmp(guctype, "enum") == 0)
3302 char querybuf[1024];
3304 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
3305 COMPLETE_WITH_QUERY(querybuf);
3307 else if (guctype && strcmp(guctype, "bool") == 0)
3308 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
3309 "1", "0", "DEFAULT");
3311 COMPLETE_WITH_CONST("DEFAULT");
3318 /* START TRANSACTION */
3319 else if (Matches1("START"))
3320 COMPLETE_WITH_CONST("TRANSACTION");
3322 /* TABLE, but not TABLE embedded in other commands */
3323 else if (Matches1("TABLE"))
3324 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3327 else if (TailMatches1("TABLESAMPLE"))
3328 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
3329 else if (TailMatches2("TABLESAMPLE", MatchAny))
3330 COMPLETE_WITH_CONST("(");
3333 else if (Matches1("TRUNCATE"))
3334 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3337 else if (Matches1("UNLISTEN"))
3338 COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s' UNION SELECT '*'");
3340 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
3341 /* If prev. word is UPDATE suggest a list of tables */
3342 else if (TailMatches1("UPDATE"))
3343 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3344 /* Complete UPDATE <table> with "SET" */
3345 else if (TailMatches2("UPDATE", MatchAny))
3346 COMPLETE_WITH_CONST("SET");
3347 /* Complete UPDATE <table> SET with list of attributes */
3348 else if (TailMatches3("UPDATE", MatchAny, "SET"))
3349 COMPLETE_WITH_ATTR(prev2_wd, "");
3350 /* UPDATE <table> SET <attr> = */
3351 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
3352 COMPLETE_WITH_CONST("=");
3355 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
3356 COMPLETE_WITH_CONST("FOR");
3357 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
3358 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3359 " UNION SELECT 'CURRENT_USER'"
3360 " UNION SELECT 'PUBLIC'"
3361 " UNION SELECT 'USER'");
3362 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
3363 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3364 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
3365 COMPLETE_WITH_CONST("SERVER");
3366 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
3367 COMPLETE_WITH_CONST("OPTIONS");
3370 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
3371 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
3373 else if (Matches1("VACUUM"))
3374 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3375 " UNION SELECT 'FULL'"
3376 " UNION SELECT 'FREEZE'"
3377 " UNION SELECT 'ANALYZE'"
3378 " UNION SELECT 'VERBOSE'");
3379 else if (Matches2("VACUUM", "FULL|FREEZE"))
3380 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3381 " UNION SELECT 'ANALYZE'"
3382 " UNION SELECT 'VERBOSE'");
3383 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
3384 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3385 " UNION SELECT 'VERBOSE'");
3386 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
3387 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3388 " UNION SELECT 'ANALYZE'");
3389 else if (Matches2("VACUUM", "VERBOSE"))
3390 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3391 " UNION SELECT 'ANALYZE'");
3392 else if (Matches2("VACUUM", "ANALYZE"))
3393 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3394 " UNION SELECT 'VERBOSE'");
3395 else if (HeadMatches1("VACUUM"))
3396 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3398 /* WITH [RECURSIVE] */
3401 * Only match when WITH is the first word, as WITH may appear in many
3404 else if (Matches1("WITH"))
3405 COMPLETE_WITH_CONST("RECURSIVE");
3408 /* Complete with list of tables */
3409 else if (Matches1("ANALYZE"))
3410 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
3413 /* Simple case of the word before the where being the table name */
3414 else if (TailMatches2(MatchAny, "WHERE"))
3415 COMPLETE_WITH_ATTR(prev2_wd, "");
3418 /* TODO: also include SRF ? */
3419 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
3420 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3423 else if (TailMatches1("JOIN"))
3424 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3426 /* Backslash commands */
3427 /* TODO: \dc \dd \dl */
3428 else if (TailMatchesCS1("\\?"))
3429 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
3430 else if (TailMatchesCS1("\\connect|\\c"))
3432 if (!recognized_connection_string(text))
3433 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3435 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
3437 if (!recognized_connection_string(prev_wd))
3438 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3440 else if (TailMatchesCS1("\\da*"))
3441 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
3442 else if (TailMatchesCS1("\\dA*"))
3443 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3444 else if (TailMatchesCS1("\\db*"))
3445 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3446 else if (TailMatchesCS1("\\dD*"))
3447 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3448 else if (TailMatchesCS1("\\des*"))
3449 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3450 else if (TailMatchesCS1("\\deu*"))
3451 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3452 else if (TailMatchesCS1("\\dew*"))
3453 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3454 else if (TailMatchesCS1("\\df*"))
3455 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3457 else if (TailMatchesCS1("\\dFd*"))
3458 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
3459 else if (TailMatchesCS1("\\dFp*"))
3460 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
3461 else if (TailMatchesCS1("\\dFt*"))
3462 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
3463 /* must be at end of \dF alternatives: */
3464 else if (TailMatchesCS1("\\dF*"))
3465 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
3467 else if (TailMatchesCS1("\\di*"))
3468 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3469 else if (TailMatchesCS1("\\dL*"))
3470 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3471 else if (TailMatchesCS1("\\dn*"))
3472 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3473 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
3474 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3475 else if (TailMatchesCS1("\\ds*"))
3476 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3477 else if (TailMatchesCS1("\\dt*"))
3478 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3479 else if (TailMatchesCS1("\\dT*"))
3480 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3481 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
3482 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3483 else if (TailMatchesCS1("\\dv*"))
3484 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3485 else if (TailMatchesCS1("\\dx*"))
3486 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
3487 else if (TailMatchesCS1("\\dm*"))
3488 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3489 else if (TailMatchesCS1("\\dE*"))
3490 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3491 else if (TailMatchesCS1("\\dy*"))
3492 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3494 /* must be at end of \d alternatives: */
3495 else if (TailMatchesCS1("\\d*"))
3496 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3498 else if (TailMatchesCS1("\\ef"))
3499 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
3500 else if (TailMatchesCS1("\\ev"))
3501 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3503 else if (TailMatchesCS1("\\encoding"))
3504 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3505 else if (TailMatchesCS1("\\h|\\help"))
3506 COMPLETE_WITH_LIST(sql_commands);
3507 else if (TailMatchesCS2("\\h|\\help", MatchAny))
3509 if (TailMatches1("DROP"))
3510 matches = completion_matches(text, drop_command_generator);
3511 else if (TailMatches1("ALTER"))
3512 matches = completion_matches(text, alter_command_generator);
3515 * CREATE is recognized by tail match elsewhere, so doesn't need to be
3519 else if (TailMatchesCS3("\\h|\\help", MatchAny, MatchAny))
3521 if (TailMatches2("CREATE|DROP", "ACCESS"))
3522 COMPLETE_WITH_CONST("METHOD");
3523 else if (TailMatches2("ALTER", "DEFAULT"))
3524 COMPLETE_WITH_CONST("PRIVILEGES");
3525 else if (TailMatches2("CREATE|ALTER|DROP", "EVENT"))
3526 COMPLETE_WITH_CONST("TRIGGER");
3527 else if (TailMatches2("CREATE|ALTER|DROP", "FOREIGN"))
3528 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
3529 else if (TailMatches2("ALTER", "LARGE"))
3530 COMPLETE_WITH_CONST("OBJECT");
3531 else if (TailMatches2("CREATE|ALTER|DROP", "MATERIALIZED"))
3532 COMPLETE_WITH_CONST("VIEW");
3533 else if (TailMatches2("CREATE|ALTER|DROP", "TEXT"))
3534 COMPLETE_WITH_CONST("SEARCH");
3535 else if (TailMatches2("CREATE|ALTER|DROP", "USER"))
3536 COMPLETE_WITH_CONST("MAPPING FOR");
3538 else if (TailMatchesCS4("\\h|\\help", MatchAny, MatchAny, MatchAny))
3540 if (TailMatches3("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
3541 COMPLETE_WITH_CONST("WRAPPER");
3542 else if (TailMatches3("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
3543 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3544 else if (TailMatches3("CREATE|ALTER|DROP", "USER", "MAPPING"))
3545 COMPLETE_WITH_CONST("FOR");
3547 else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
3548 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3549 else if (TailMatchesCS1("\\password"))
3550 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3551 else if (TailMatchesCS1("\\pset"))
3553 static const char *const my_list[] =
3554 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3555 "footer", "format", "linestyle", "null", "numericlocale",
3556 "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3557 "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3558 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3560 COMPLETE_WITH_LIST_CS(my_list);
3562 else if (TailMatchesCS2("\\pset", MatchAny))
3564 if (TailMatchesCS1("format"))
3566 static const char *const my_list[] =
3567 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3568 "latex", "latex-longtable", "troff-ms", NULL};
3570 COMPLETE_WITH_LIST_CS(my_list);
3572 else if (TailMatchesCS1("linestyle"))
3573 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3574 else if (TailMatchesCS1("pager"))
3575 COMPLETE_WITH_LIST_CS3("on", "off", "always");
3576 else if (TailMatchesCS1("unicode_border_linestyle|"
3577 "unicode_column_linestyle|"
3578 "unicode_header_linestyle"))
3579 COMPLETE_WITH_LIST_CS2("single", "double");
3581 else if (TailMatchesCS1("\\unset"))
3582 matches = complete_from_variables(text, "", "", true);
3583 else if (TailMatchesCS1("\\set"))
3584 matches = complete_from_variables(text, "", "", false);
3585 else if (TailMatchesCS2("\\set", MatchAny))
3587 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3588 "SINGLELINE|SINGLESTEP"))
3589 COMPLETE_WITH_LIST_CS2("on", "off");
3590 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3591 COMPLETE_WITH_LIST_CS4("lower", "upper",
3592 "preserve-lower", "preserve-upper");
3593 else if (TailMatchesCS1("ECHO"))
3594 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3595 else if (TailMatchesCS1("ECHO_HIDDEN"))
3596 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3597 else if (TailMatchesCS1("HISTCONTROL"))
3598 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3599 "ignoreboth", "none");
3600 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3601 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3602 else if (TailMatchesCS1("SHOW_CONTEXT"))
3603 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3604 else if (TailMatchesCS1("VERBOSITY"))
3605 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3607 else if (TailMatchesCS1("\\sf*"))
3608 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
3609 else if (TailMatchesCS1("\\sv*"))
3610 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3611 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3612 "\\ir|\\include_relative|\\o|\\out|"
3613 "\\s|\\w|\\write|\\lo_import"))
3615 completion_charp = "\\";
3616 matches = completion_matches(text, complete_from_files);
3620 * Finally, we look through the list of "things", such as TABLE, INDEX and
3621 * check if that was the previous word. If so, execute the query to get a
3628 for (i = 0; words_after_create[i].name; i++)
3630 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3632 if (words_after_create[i].query)
3633 COMPLETE_WITH_QUERY(words_after_create[i].query);
3634 else if (words_after_create[i].vquery)
3635 COMPLETE_WITH_VERSIONED_QUERY(words_after_create[i].vquery);
3636 else if (words_after_create[i].squery)
3637 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(words_after_create[i].squery,
3645 * If we still don't have anything to match we have to fabricate some sort
3646 * of default list. If we were to just return NULL, readline automatically
3647 * attempts filename completion, and that's usually no good.
3649 if (matches == NULL)
3651 COMPLETE_WITH_CONST("");
3652 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3653 rl_completion_append_character = '\0';
3658 free(previous_words);
3661 /* Return our Grand List O' Matches */
3667 * GENERATOR FUNCTIONS
3669 * These functions do all the actual work of completing the input. They get
3670 * passed the text so far and the count how many times they have been called
3671 * so far with the same text.
3672 * If you read the above carefully, you'll see that these don't get called
3673 * directly but through the readline interface.
3674 * The return value is expected to be the full completion of the text, going
3675 * through a list each time, or NULL if there are no more matches. The string
3676 * will be free()'d by readline, so you must run it through strdup() or
3677 * something of that sort.
3681 * Common routine for create_command_generator and drop_command_generator.
3682 * Entries that have 'excluded' flags are not returned.
3685 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3687 static int list_index,
3691 /* If this is the first time for this completion, init some values */
3695 string_length = strlen(text);
3698 /* find something that matches */
3699 while ((name = words_after_create[list_index++].name))
3701 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3702 !(words_after_create[list_index - 1].flags & excluded))
3703 return pg_strdup_keyword_case(name, text);
3705 /* if nothing matches, return NULL */
3710 * This one gives you one from a list of things you can put after CREATE
3714 create_command_generator(const char *text, int state)
3716 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3720 * This function gives you a list of things you can put after a DROP command.
3723 drop_command_generator(const char *text, int state)
3725 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3729 * This function gives you a list of things you can put after an ALTER command.
3732 alter_command_generator(const char *text, int state)
3734 return create_or_drop_command_generator(text, state, THING_NO_ALTER);
3738 * These functions generate lists using server queries.
3739 * They are all wrappers for _complete_from_query.
3743 complete_from_query(const char *text, int state)
3745 /* query is assumed to work for any server version */
3746 return _complete_from_query(completion_charp, NULL, text, state);
3750 complete_from_versioned_query(const char *text, int state)
3752 const VersionedQuery *vquery = completion_vquery;
3754 /* Find appropriate array element */
3755 while (pset.sversion < vquery->min_server_version)
3757 /* Fail completion if server is too old */
3758 if (vquery->query == NULL)
3761 return _complete_from_query(vquery->query, NULL, text, state);
3765 complete_from_schema_query(const char *text, int state)
3767 /* query is assumed to work for any server version */
3768 return _complete_from_query(completion_charp, completion_squery,
3773 complete_from_versioned_schema_query(const char *text, int state)
3775 const SchemaQuery *squery = completion_squery;
3776 const VersionedQuery *vquery = completion_vquery;
3778 /* Find appropriate array element */
3779 while (pset.sversion < squery->min_server_version)
3781 /* Fail completion if server is too old */
3782 if (squery->catname == NULL)
3785 /* Likewise for the add-on text, if any */
3788 while (pset.sversion < vquery->min_server_version)
3790 if (vquery->query == NULL)
3794 return _complete_from_query(vquery ? vquery->query : NULL,
3795 squery, text, state);
3800 * This creates a list of matching things, according to a query described by
3801 * the initial arguments. The caller has already done any work needed to
3802 * select the appropriate query for the server's version.
3804 * The query can be one of two kinds:
3806 * 1. A simple query which must contain a %d and a %s, which will be replaced
3807 * by the string length of the text and the text itself. The query may also
3808 * have up to four more %s in it; the first two such will be replaced by the
3809 * value of completion_info_charp, the next two by the value of
3810 * completion_info_charp2.
3812 * 2. A schema query used for completion of both schema and relation names.
3813 * These are more complex and must contain in the following order:
3814 * %d %s %d %s %d %s %s %d %s
3815 * where %d is the string length of the text and %s the text itself.
3817 * If both simple_query and schema_query are non-NULL, then we construct
3818 * a schema query and append the (uninterpreted) string simple_query to it.
3820 * It is assumed that strings should be escaped to become SQL literals
3821 * (that is, what is in the query is actually ... '%s' ...)
3823 * See top of file for examples of both kinds of query.
3825 * "text" and "state" are supplied by readline.
3828 _complete_from_query(const char *simple_query,
3829 const SchemaQuery *schema_query,
3830 const char *text, int state)
3832 static int list_index,
3834 static PGresult *result = NULL;
3837 * If this is the first time for this completion, we fetch a list of our
3838 * "things" from the backend.
3842 PQExpBufferData query_buffer;
3845 char *e_info_charp2;
3846 const char *pstr = text;
3847 int char_length = 0;
3850 byte_length = strlen(text);
3853 * Count length as number of characters (not bytes), for passing to
3859 pstr += PQmblen(pstr, pset.encoding);
3862 /* Free any prior result */
3866 /* Set up suitably-escaped copies of textual inputs */
3867 e_text = escape_string(text);
3869 if (completion_info_charp)
3870 e_info_charp = escape_string(completion_info_charp);
3872 e_info_charp = NULL;
3874 if (completion_info_charp2)
3875 e_info_charp2 = escape_string(completion_info_charp2);
3877 e_info_charp2 = NULL;
3879 initPQExpBuffer(&query_buffer);
3883 /* schema_query gives us the pieces to assemble */
3884 const char *qualresult = schema_query->qualresult;
3886 if (qualresult == NULL)
3887 qualresult = schema_query->result;
3889 /* Get unqualified names matching the input-so-far */
3890 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3891 schema_query->result,
3892 schema_query->catname);
3893 if (schema_query->selcondition)
3894 appendPQExpBuffer(&query_buffer, "%s AND ",
3895 schema_query->selcondition);
3896 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3897 schema_query->result,
3898 char_length, e_text);
3899 appendPQExpBuffer(&query_buffer, " AND %s",
3900 schema_query->viscondition);
3903 * When fetching relation names, suppress system catalogs unless
3904 * the input-so-far begins with "pg_". This is a compromise
3905 * between not offering system catalogs for completion at all, and
3906 * having them swamp the result when the input is just "p".
3908 if (strcmp(schema_query->catname,
3909 "pg_catalog.pg_class c") == 0 &&
3910 strncmp(text, "pg_", 3) !=0)
3912 appendPQExpBufferStr(&query_buffer,
3913 " AND c.relnamespace <> (SELECT oid FROM"
3914 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3918 * Add in matching schema names, but only if there is more than
3919 * one potential match among schema names.
3921 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3922 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3923 "FROM pg_catalog.pg_namespace n "
3924 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3925 char_length, e_text);
3926 appendPQExpBuffer(&query_buffer,
3927 " AND (SELECT pg_catalog.count(*)"
3928 " FROM pg_catalog.pg_namespace"
3929 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3930 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3931 char_length, e_text);
3934 * Add in matching qualified names, but only if there is exactly
3935 * one schema matching the input-so-far.
3937 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3938 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3939 "FROM %s, pg_catalog.pg_namespace n "
3940 "WHERE %s = n.oid AND ",
3942 schema_query->catname,
3943 schema_query->namespace);
3944 if (schema_query->selcondition)
3945 appendPQExpBuffer(&query_buffer, "%s AND ",
3946 schema_query->selcondition);
3947 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3949 char_length, e_text);
3952 * This condition exploits the single-matching-schema rule to
3953 * speed up the query
3955 appendPQExpBuffer(&query_buffer,
3956 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3957 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3958 char_length, e_text);
3959 appendPQExpBuffer(&query_buffer,
3960 " AND (SELECT pg_catalog.count(*)"
3961 " FROM pg_catalog.pg_namespace"
3962 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3963 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3964 char_length, e_text);
3966 /* If an addon query was provided, use it */
3968 appendPQExpBuffer(&query_buffer, "\n%s", simple_query);
3972 Assert(simple_query);
3973 /* simple_query is an sprintf-style format string */
3974 appendPQExpBuffer(&query_buffer, simple_query,
3975 char_length, e_text,
3976 e_info_charp, e_info_charp,
3977 e_info_charp2, e_info_charp2);
3980 /* Limit the number of records in the result */
3981 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3982 completion_max_records);
3984 result = exec_query(query_buffer.data);
3986 termPQExpBuffer(&query_buffer);
3991 free(e_info_charp2);
3994 /* Find something that matches */
3995 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3999 while (list_index < PQntuples(result) &&
4000 (item = PQgetvalue(result, list_index++, 0)))
4001 if (pg_strncasecmp(text, item, byte_length) == 0)
4002 return pg_strdup(item);
4005 /* If nothing matches, free the db structure and return null */
4013 * This function returns in order one of a fixed, NULL pointer terminated list
4014 * of strings (if matching). This can be used if there are only a fixed number
4015 * SQL words that can appear at certain spot.
4018 complete_from_list(const char *text, int state)
4020 static int string_length,
4023 static bool casesensitive;
4026 /* need to have a list */
4027 Assert(completion_charpp != NULL);
4029 /* Initialization */
4033 string_length = strlen(text);
4034 casesensitive = completion_case_sensitive;
4038 while ((item = completion_charpp[list_index++]))
4040 /* First pass is case sensitive */
4041 if (casesensitive && strncmp(text, item, string_length) == 0)
4044 return pg_strdup(item);
4047 /* Second pass is case insensitive, don't bother counting matches */
4048 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
4050 if (completion_case_sensitive)
4051 return pg_strdup(item);
4055 * If case insensitive matching was requested initially,
4056 * adjust the case according to setting.
4058 return pg_strdup_keyword_case(item, text);
4063 * No matches found. If we're not case insensitive already, lets switch to
4064 * being case insensitive and try again
4066 if (casesensitive && matches == 0)
4068 casesensitive = false;
4071 return complete_from_list(text, state);
4074 /* If no more matches, return null. */
4080 * This function returns one fixed string the first time even if it doesn't
4081 * match what's there, and nothing the second time. This should be used if
4082 * there is only one possibility that can appear at a certain spot, so
4083 * misspellings will be overwritten. The string to be passed must be in
4087 complete_from_const(const char *text, int state)
4089 Assert(completion_charp != NULL);
4092 if (completion_case_sensitive)
4093 return pg_strdup(completion_charp);
4097 * If case insensitive matching was requested initially, adjust
4098 * the case according to setting.
4100 return pg_strdup_keyword_case(completion_charp, text);
4108 * This function appends the variable name with prefix and suffix to
4109 * the variable names array.
4112 append_variable_names(char ***varnames, int *nvars,
4113 int *maxvars, const char *varname,
4114 const char *prefix, const char *suffix)
4116 if (*nvars >= *maxvars)
4119 *varnames = (char **) pg_realloc(*varnames,
4120 ((*maxvars) + 1) * sizeof(char *));
4123 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
4128 * This function supports completion with the name of a psql variable.
4129 * The variable names can be prefixed and suffixed with additional text
4130 * to support quoting usages. If need_value is true, only variables
4131 * that are currently set are included; otherwise, special variables
4132 * (those that have hooks) are included even if currently unset.
4135 complete_from_variables(const char *text, const char *prefix, const char *suffix,
4143 struct _variable *ptr;
4145 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
4147 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
4149 if (need_value && !(ptr->value))
4151 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
4155 varnames[nvars] = NULL;
4156 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
4158 for (i = 0; i < nvars; i++)
4167 * This function wraps rl_filename_completion_function() to strip quotes from
4168 * the input before searching for matches and to quote any matches for which
4169 * the consuming command will require it.
4172 complete_from_files(const char *text, int state)
4174 static const char *unquoted_text;
4175 char *unquoted_match;
4180 /* Initialization: stash the unquoted input. */
4181 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
4182 false, true, pset.encoding);
4183 /* expect a NULL return for the empty string only */
4186 Assert(*text == '\0');
4187 unquoted_text = text;
4191 unquoted_match = filename_completion_function(unquoted_text, state);
4195 * Caller sets completion_charp to a zero- or one-character string
4196 * containing the escape character. This is necessary since \copy has
4197 * no escape character, but every other backslash command recognizes
4198 * "\" as an escape character. Since we have only two callers, don't
4199 * bother providing a macro to simplify this.
4201 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
4202 '\'', *completion_charp, pset.encoding);
4204 free(unquoted_match);
4206 ret = unquoted_match;
4213 /* HELPER FUNCTIONS */
4217 * Make a pg_strdup copy of s and convert the case according to
4218 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
4221 pg_strdup_keyword_case(const char *s, const char *ref)
4225 unsigned char first = ref[0];
4229 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
4230 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
4231 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
4232 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
4234 for (p = ret; *p; p++)
4235 *p = pg_tolower((unsigned char) *p);
4239 for (p = ret; *p; p++)
4240 *p = pg_toupper((unsigned char) *p);
4248 * escape_string - Escape argument for use as string literal.
4250 * The returned value has to be freed.
4253 escape_string(const char *text)
4258 text_length = strlen(text);
4260 result = pg_malloc(text_length * 2 + 1);
4261 PQescapeStringConn(pset.db, result, text, text_length, NULL);
4268 * Execute a query and report any errors. This should be the preferred way of
4269 * talking to the database in this file.
4272 exec_query(const char *query)
4276 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
4279 result = PQexec(pset.db, query);
4281 if (PQresultStatus(result) != PGRES_TUPLES_OK)
4284 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
4285 PQerrorMessage(pset.db), query);
4296 * Parse all the word(s) before point.
4298 * Returns a malloc'd array of character pointers that point into the malloc'd
4299 * data array returned to *buffer; caller must free() both of these when done.
4300 * *nwords receives the number of words found, ie, the valid length of the
4303 * Words are returned right to left, that is, previous_words[0] gets the last
4304 * word before point, previous_words[1] the next-to-last, etc.
4307 get_previous_words(int point, char **buffer, int *nwords)
4309 char **previous_words;
4312 int words_found = 0;
4316 * If we have anything in tab_completion_query_buf, paste it together with
4317 * rl_line_buffer to construct the full query. Otherwise we can just use
4318 * rl_line_buffer as the input string.
4320 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
4322 i = tab_completion_query_buf->len;
4323 buf = pg_malloc(point + i + 2);
4324 memcpy(buf, tab_completion_query_buf->data, i);
4326 memcpy(buf + i, rl_line_buffer, point);
4329 /* Readjust point to reference appropriate offset in buf */
4333 buf = rl_line_buffer;
4336 * Allocate an array of string pointers and a buffer to hold the strings
4337 * themselves. The worst case is that the line contains only
4338 * non-whitespace WORD_BREAKS characters, making each one a separate word.
4339 * This is usually much more space than we need, but it's cheaper than
4340 * doing a separate malloc() for each word.
4342 previous_words = (char **) pg_malloc(point * sizeof(char *));
4343 *buffer = outptr = (char *) pg_malloc(point * 2);
4346 * First we look for a non-word char before the current point. (This is
4347 * probably useless, if readline is on the same page as we are about what
4348 * is a word, but if so it's cheap.)
4350 for (i = point - 1; i >= 0; i--)
4352 if (strchr(WORD_BREAKS, buf[i]))
4358 * Now parse words, working backwards, until we hit start of line. The
4359 * backwards scan has some interesting but intentional properties
4360 * concerning parenthesis handling.
4366 bool inquotes = false;
4367 int parentheses = 0;
4369 /* now find the first non-space which then constitutes the end */
4371 for (i = point; i >= 0; i--)
4373 if (!isspace((unsigned char) buf[i]))
4379 /* if no end found, we're done */
4384 * Otherwise we now look for the start. The start is either the last
4385 * character before any word-break character going backwards from the
4386 * end, or it's simply character 0. We also handle open quotes and
4389 for (start = end; start > 0; start--)
4391 if (buf[start] == '"')
4392 inquotes = !inquotes;
4395 if (buf[start] == ')')
4397 else if (buf[start] == '(')
4399 if (--parentheses <= 0)
4402 else if (parentheses == 0 &&
4403 strchr(WORD_BREAKS, buf[start - 1]))
4408 /* Return the word located at start to end inclusive */
4409 previous_words[words_found++] = outptr;
4410 i = end - start + 1;
4411 memcpy(outptr, &buf[start], i);
4415 /* Continue searching */
4419 /* Release parsing input workspace, if we made one above */
4420 if (buf != rl_line_buffer)
4423 *nwords = words_found;
4424 return previous_words;
4428 * Look up the type for the GUC variable with the passed name.
4430 * Returns NULL if the variable is unknown. Otherwise the returned string,
4431 * containing the type, has to be freed.
4434 get_guctype(const char *varname)
4436 PQExpBufferData query_buffer;
4439 char *guctype = NULL;
4441 e_varname = escape_string(varname);
4443 initPQExpBuffer(&query_buffer);
4444 appendPQExpBuffer(&query_buffer,
4445 "SELECT vartype FROM pg_catalog.pg_settings "
4446 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
4449 result = exec_query(query_buffer.data);
4450 termPQExpBuffer(&query_buffer);
4453 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
4454 guctype = pg_strdup(PQgetvalue(result, 0, 0));
4464 * Surround a string with single quotes. This works for both SQL and
4465 * psql internal. Currently disabled because it is reported not to
4466 * cooperate with certain versions of readline.
4469 quote_file_name(char *text, int match_type, char *quote_pointer)
4474 (void) quote_pointer; /* not used */
4476 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
4477 s = pg_malloc(length);
4479 strcpy(s + 1, text);
4480 if (match_type == SINGLE_MATCH)
4481 s[length - 2] = '\'';
4482 s[length - 1] = '\0';
4487 dequote_file_name(char *text, char quote_char)
4493 return pg_strdup(text);
4495 length = strlen(text);
4496 s = pg_malloc(length - 2 + 1);
4497 strlcpy(s, text +1, length - 2 + 1);
4501 #endif /* NOT_USED */
4503 #endif /* USE_READLINE */