2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2016, 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 "pqexpbuffer.h"
47 #include "stringutils.h"
49 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
50 #define filename_completion_function rl_filename_completion_function
52 /* missing in some header files */
53 extern char *filename_completion_function();
56 #ifdef HAVE_RL_COMPLETION_MATCHES
57 #define completion_matches rl_completion_matches
60 /* word break characters */
61 #define WORD_BREAKS "\t\n@$><=;|&{() "
64 * Since readline doesn't let us pass any state through to the tab completion
65 * callback, we have to use this global variable to let get_previous_words()
66 * get at the previous lines of the current command. Ick.
68 PQExpBuffer tab_completion_query_buf = NULL;
71 * This struct is used to define "schema queries", which are custom-built
72 * to obtain possibly-schema-qualified names of database objects. There is
73 * enough similarity in the structure that we don't want to repeat it each
74 * time. So we put the components of each query into this struct and
75 * assemble them with the common boilerplate in _complete_from_query().
77 typedef struct SchemaQuery
80 * Name of catalog or catalogs to be queried, with alias, eg.
81 * "pg_catalog.pg_class c". Note that "pg_namespace n" will be added.
86 * Selection condition --- only rows meeting this condition are candidates
87 * to display. If catname mentions multiple tables, include the necessary
88 * join condition here. For example, "c.relkind = 'r'". Write NULL (not
89 * an empty string) if not needed.
91 const char *selcondition;
94 * Visibility condition --- which rows are visible without schema
95 * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
97 const char *viscondition;
100 * Namespace --- name of field to join to pg_namespace.oid. For example,
103 const char *namespace;
106 * Result --- the appropriately-quoted name to return, in the case of an
107 * unqualified name. For example, "pg_catalog.quote_ident(c.relname)".
112 * In some cases a different result must be used for qualified names.
113 * Enter that here, or write NULL if result can be used.
115 const char *qualresult;
119 /* Store maximum number of records we want from database queries
120 * (implemented via SELECT ... LIMIT xx).
122 static int completion_max_records;
125 * Communication variables set by COMPLETE_WITH_FOO macros and then used by
126 * the completion callback functions. Ugly but there is no better way.
128 static const char *completion_charp; /* to pass a string */
129 static const char *const * completion_charpp; /* to pass a list of strings */
130 static const char *completion_info_charp; /* to pass a second string */
131 static const char *completion_info_charp2; /* to pass a third string */
132 static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
133 static bool completion_case_sensitive; /* completion is case sensitive */
136 * A few macros to ease typing. You can use these to complete the given
138 * 1) The results from a query you pass it. (Perhaps one of those below?)
139 * 2) The results from a schema query you pass it.
140 * 3) The items from a null-pointer-terminated list (with or without
141 * case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
142 * 4) A string constant.
143 * 5) The list of attributes of the given table (possibly schema-qualified).
144 * 6/ The list of arguments to the given function (possibly schema-qualified).
146 #define COMPLETE_WITH_QUERY(query) \
148 completion_charp = query; \
149 matches = completion_matches(text, complete_from_query); \
152 #define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
154 completion_squery = &(query); \
155 completion_charp = addon; \
156 matches = completion_matches(text, complete_from_schema_query); \
159 #define COMPLETE_WITH_LIST_CS(list) \
161 completion_charpp = list; \
162 completion_case_sensitive = true; \
163 matches = completion_matches(text, complete_from_list); \
166 #define COMPLETE_WITH_LIST(list) \
168 completion_charpp = list; \
169 completion_case_sensitive = false; \
170 matches = completion_matches(text, complete_from_list); \
173 #define COMPLETE_WITH_CONST(string) \
175 completion_charp = string; \
176 completion_case_sensitive = false; \
177 matches = completion_matches(text, complete_from_const); \
180 #define COMPLETE_WITH_ATTR(relation, addon) \
182 char *_completion_schema; \
183 char *_completion_table; \
185 _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
186 false, false, pset.encoding); \
187 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
188 false, false, pset.encoding); \
189 _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
190 false, false, pset.encoding); \
191 if (_completion_table == NULL) \
193 completion_charp = Query_for_list_of_attributes addon; \
194 completion_info_charp = relation; \
198 completion_charp = Query_for_list_of_attributes_with_schema addon; \
199 completion_info_charp = _completion_table; \
200 completion_info_charp2 = _completion_schema; \
202 matches = completion_matches(text, complete_from_query); \
205 #define COMPLETE_WITH_ENUM_VALUE(type) \
207 char *_completion_schema; \
208 char *_completion_type; \
210 _completion_schema = strtokx(type, " \t\n\r", ".", "\"", 0, \
211 false, false, pset.encoding); \
212 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
213 false, false, pset.encoding); \
214 _completion_type = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
215 false, false, pset.encoding); \
216 if (_completion_type == NULL)\
218 completion_charp = Query_for_list_of_enum_values; \
219 completion_info_charp = type; \
223 completion_charp = Query_for_list_of_enum_values_with_schema; \
224 completion_info_charp = _completion_type; \
225 completion_info_charp2 = _completion_schema; \
227 matches = completion_matches(text, complete_from_query); \
230 #define COMPLETE_WITH_FUNCTION_ARG(function) \
232 char *_completion_schema; \
233 char *_completion_function; \
235 _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
236 false, false, pset.encoding); \
237 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
238 false, false, pset.encoding); \
239 _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
240 false, false, pset.encoding); \
241 if (_completion_function == NULL) \
243 completion_charp = Query_for_list_of_arguments; \
244 completion_info_charp = function; \
248 completion_charp = Query_for_list_of_arguments_with_schema; \
249 completion_info_charp = _completion_function; \
250 completion_info_charp2 = _completion_schema; \
252 matches = completion_matches(text, complete_from_query); \
256 * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
257 * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
259 #define COMPLETE_WITH_LIST2(s1, s2) \
261 static const char *const list[] = { s1, s2, NULL }; \
262 COMPLETE_WITH_LIST(list); \
265 #define COMPLETE_WITH_LIST3(s1, s2, s3) \
267 static const char *const list[] = { s1, s2, s3, NULL }; \
268 COMPLETE_WITH_LIST(list); \
271 #define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
273 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
274 COMPLETE_WITH_LIST(list); \
277 #define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
279 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
280 COMPLETE_WITH_LIST(list); \
283 #define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \
285 static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \
286 COMPLETE_WITH_LIST(list); \
289 #define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \
291 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \
292 COMPLETE_WITH_LIST(list); \
295 #define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \
297 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \
298 COMPLETE_WITH_LIST(list); \
301 #define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
303 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
304 COMPLETE_WITH_LIST(list); \
307 #define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
309 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
310 COMPLETE_WITH_LIST(list); \
314 * Likewise for COMPLETE_WITH_LIST_CS.
316 #define COMPLETE_WITH_LIST_CS2(s1, s2) \
318 static const char *const list[] = { s1, s2, NULL }; \
319 COMPLETE_WITH_LIST_CS(list); \
322 #define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
324 static const char *const list[] = { s1, s2, s3, NULL }; \
325 COMPLETE_WITH_LIST_CS(list); \
328 #define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
330 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
331 COMPLETE_WITH_LIST_CS(list); \
334 #define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
336 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
337 COMPLETE_WITH_LIST_CS(list); \
341 * Assembly instructions for schema queries
344 static const SchemaQuery Query_for_list_of_aggregates = {
346 "pg_catalog.pg_proc p",
350 "pg_catalog.pg_function_is_visible(p.oid)",
354 "pg_catalog.quote_ident(p.proname)",
359 static const SchemaQuery Query_for_list_of_datatypes = {
361 "pg_catalog.pg_type t",
362 /* selcondition --- ignore table rowtypes and array types */
364 " OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
365 "AND t.typname !~ '^_'",
367 "pg_catalog.pg_type_is_visible(t.oid)",
371 "pg_catalog.format_type(t.oid, NULL)",
373 "pg_catalog.quote_ident(t.typname)"
376 static const SchemaQuery Query_for_list_of_domains = {
378 "pg_catalog.pg_type t",
382 "pg_catalog.pg_type_is_visible(t.oid)",
386 "pg_catalog.quote_ident(t.typname)",
391 static const SchemaQuery Query_for_list_of_functions = {
393 "pg_catalog.pg_proc p",
397 "pg_catalog.pg_function_is_visible(p.oid)",
401 "pg_catalog.quote_ident(p.proname)",
406 static const SchemaQuery Query_for_list_of_indexes = {
408 "pg_catalog.pg_class c",
410 "c.relkind IN ('i')",
412 "pg_catalog.pg_table_is_visible(c.oid)",
416 "pg_catalog.quote_ident(c.relname)",
421 static const SchemaQuery Query_for_list_of_sequences = {
423 "pg_catalog.pg_class c",
425 "c.relkind IN ('S')",
427 "pg_catalog.pg_table_is_visible(c.oid)",
431 "pg_catalog.quote_ident(c.relname)",
436 static const SchemaQuery Query_for_list_of_foreign_tables = {
438 "pg_catalog.pg_class c",
440 "c.relkind IN ('f')",
442 "pg_catalog.pg_table_is_visible(c.oid)",
446 "pg_catalog.quote_ident(c.relname)",
451 static const SchemaQuery Query_for_list_of_tables = {
453 "pg_catalog.pg_class c",
455 "c.relkind IN ('r', 'P')",
457 "pg_catalog.pg_table_is_visible(c.oid)",
461 "pg_catalog.quote_ident(c.relname)",
466 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
468 "pg_catalog.pg_constraint c",
472 "true", /* there is no pg_constraint_is_visible */
476 "pg_catalog.quote_ident(c.conname)",
481 /* Relations supporting INSERT, UPDATE or DELETE */
482 static const SchemaQuery Query_for_list_of_updatables = {
484 "pg_catalog.pg_class c",
486 "c.relkind IN ('r', 'f', 'v', 'P')",
488 "pg_catalog.pg_table_is_visible(c.oid)",
492 "pg_catalog.quote_ident(c.relname)",
497 static const SchemaQuery Query_for_list_of_relations = {
499 "pg_catalog.pg_class c",
503 "pg_catalog.pg_table_is_visible(c.oid)",
507 "pg_catalog.quote_ident(c.relname)",
512 static const SchemaQuery Query_for_list_of_tsvmf = {
514 "pg_catalog.pg_class c",
516 "c.relkind IN ('r', 'S', 'v', 'm', 'f', 'P')",
518 "pg_catalog.pg_table_is_visible(c.oid)",
522 "pg_catalog.quote_ident(c.relname)",
527 static const SchemaQuery Query_for_list_of_tmf = {
529 "pg_catalog.pg_class c",
531 "c.relkind IN ('r', 'm', 'f')",
533 "pg_catalog.pg_table_is_visible(c.oid)",
537 "pg_catalog.quote_ident(c.relname)",
542 static const SchemaQuery Query_for_list_of_tm = {
544 "pg_catalog.pg_class c",
546 "c.relkind IN ('r', 'm')",
548 "pg_catalog.pg_table_is_visible(c.oid)",
552 "pg_catalog.quote_ident(c.relname)",
557 static const SchemaQuery Query_for_list_of_views = {
559 "pg_catalog.pg_class c",
561 "c.relkind IN ('v')",
563 "pg_catalog.pg_table_is_visible(c.oid)",
567 "pg_catalog.quote_ident(c.relname)",
572 static const SchemaQuery Query_for_list_of_matviews = {
574 "pg_catalog.pg_class c",
576 "c.relkind IN ('m')",
578 "pg_catalog.pg_table_is_visible(c.oid)",
582 "pg_catalog.quote_ident(c.relname)",
589 * Queries to get lists of names of various kinds of things, possibly
590 * restricted to names matching a partially entered name. In these queries,
591 * the first %s will be replaced by the text entered so far (suitably escaped
592 * to become a SQL literal string). %d will be replaced by the length of the
593 * string (in unescaped form). A second and third %s, if present, will be
594 * replaced by a suitably-escaped version of the string provided in
595 * completion_info_charp. A fourth and fifth %s are similarly replaced by
596 * completion_info_charp2.
598 * Beware that the allowed sequences of %s and %d are determined by
599 * _complete_from_query().
602 #define Query_for_list_of_attributes \
603 "SELECT pg_catalog.quote_ident(attname) "\
604 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
605 " WHERE c.oid = a.attrelid "\
606 " AND a.attnum > 0 "\
607 " AND NOT a.attisdropped "\
608 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
609 " AND (pg_catalog.quote_ident(relname)='%s' "\
610 " OR '\"' || relname || '\"'='%s') "\
611 " AND pg_catalog.pg_table_is_visible(c.oid)"
613 #define Query_for_list_of_attributes_with_schema \
614 "SELECT pg_catalog.quote_ident(attname) "\
615 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
616 " WHERE c.oid = a.attrelid "\
617 " AND n.oid = c.relnamespace "\
618 " AND a.attnum > 0 "\
619 " AND NOT a.attisdropped "\
620 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
621 " AND (pg_catalog.quote_ident(relname)='%s' "\
622 " OR '\"' || relname || '\"' ='%s') "\
623 " AND (pg_catalog.quote_ident(nspname)='%s' "\
624 " OR '\"' || nspname || '\"' ='%s') "
626 #define Query_for_list_of_enum_values \
627 "SELECT pg_catalog.quote_literal(enumlabel) "\
628 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t "\
629 " WHERE t.oid = e.enumtypid "\
630 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
631 " AND (pg_catalog.quote_ident(typname)='%s' "\
632 " OR '\"' || typname || '\"'='%s') "\
633 " AND pg_catalog.pg_type_is_visible(t.oid)"
635 #define Query_for_list_of_enum_values_with_schema \
636 "SELECT pg_catalog.quote_literal(enumlabel) "\
637 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
638 " WHERE t.oid = e.enumtypid "\
639 " AND n.oid = t.typnamespace "\
640 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
641 " AND (pg_catalog.quote_ident(typname)='%s' "\
642 " OR '\"' || typname || '\"'='%s') "\
643 " AND (pg_catalog.quote_ident(nspname)='%s' "\
644 " OR '\"' || nspname || '\"' ='%s') "
646 #define Query_for_list_of_template_databases \
647 "SELECT pg_catalog.quote_ident(d.datname) "\
648 " FROM pg_catalog.pg_database d "\
649 " WHERE substring(pg_catalog.quote_ident(d.datname),1,%d)='%s' "\
650 " AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
652 #define Query_for_list_of_databases \
653 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
654 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
656 #define Query_for_list_of_tablespaces \
657 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
658 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
660 #define Query_for_list_of_encodings \
661 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
662 " FROM pg_catalog.pg_conversion "\
663 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
665 #define Query_for_list_of_languages \
666 "SELECT pg_catalog.quote_ident(lanname) "\
667 " FROM pg_catalog.pg_language "\
668 " WHERE lanname != 'internal' "\
669 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
671 #define Query_for_list_of_schemas \
672 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
673 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
675 #define Query_for_list_of_alter_system_set_vars \
677 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
678 " WHERE context != 'internal') ss "\
679 " WHERE substring(name,1,%d)='%s'"\
680 " UNION ALL SELECT 'all' ss"
682 #define Query_for_list_of_set_vars \
684 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
685 " WHERE context IN ('user', 'superuser') "\
686 " UNION ALL SELECT 'constraints' "\
687 " UNION ALL SELECT 'transaction' "\
688 " UNION ALL SELECT 'session' "\
689 " UNION ALL SELECT 'role' "\
690 " UNION ALL SELECT 'tablespace' "\
691 " UNION ALL SELECT 'all') ss "\
692 " WHERE substring(name,1,%d)='%s'"
694 #define Query_for_list_of_show_vars \
696 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
697 " UNION ALL SELECT 'session authorization' "\
698 " UNION ALL SELECT 'all') ss "\
699 " WHERE substring(name,1,%d)='%s'"
701 #define Query_for_list_of_roles \
702 " SELECT pg_catalog.quote_ident(rolname) "\
703 " FROM pg_catalog.pg_roles "\
704 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
706 #define Query_for_list_of_grant_roles \
707 " SELECT pg_catalog.quote_ident(rolname) "\
708 " FROM pg_catalog.pg_roles "\
709 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
710 " UNION ALL SELECT 'PUBLIC'"\
711 " UNION ALL SELECT 'CURRENT_USER'"\
712 " UNION ALL SELECT 'SESSION_USER'"
714 /* the silly-looking length condition is just to eat up the current word */
715 #define Query_for_table_owning_index \
716 "SELECT pg_catalog.quote_ident(c1.relname) "\
717 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
718 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
719 " and (%d = pg_catalog.length('%s'))"\
720 " and pg_catalog.quote_ident(c2.relname)='%s'"\
721 " and pg_catalog.pg_table_is_visible(c2.oid)"
723 /* the silly-looking length condition is just to eat up the current word */
724 #define Query_for_index_of_table \
725 "SELECT pg_catalog.quote_ident(c2.relname) "\
726 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
727 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
728 " and (%d = pg_catalog.length('%s'))"\
729 " and pg_catalog.quote_ident(c1.relname)='%s'"\
730 " and pg_catalog.pg_table_is_visible(c2.oid)"
732 /* the silly-looking length condition is just to eat up the current word */
733 #define Query_for_constraint_of_table \
734 "SELECT pg_catalog.quote_ident(conname) "\
735 " FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
736 " WHERE c1.oid=conrelid and (%d = pg_catalog.length('%s'))"\
737 " and pg_catalog.quote_ident(c1.relname)='%s'"\
738 " and pg_catalog.pg_table_is_visible(c1.oid)"
740 #define Query_for_all_table_constraints \
741 "SELECT pg_catalog.quote_ident(conname) "\
742 " FROM pg_catalog.pg_constraint c "\
743 " WHERE c.conrelid <> 0 "
745 /* the silly-looking length condition is just to eat up the current word */
746 #define Query_for_constraint_of_type \
747 "SELECT pg_catalog.quote_ident(conname) "\
748 " FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
749 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
750 " and pg_catalog.quote_ident(t.typname)='%s'"\
751 " and pg_catalog.pg_type_is_visible(t.oid)"
753 /* the silly-looking length condition is just to eat up the current word */
754 #define Query_for_list_of_tables_for_constraint \
755 "SELECT pg_catalog.quote_ident(relname) "\
756 " FROM pg_catalog.pg_class"\
757 " WHERE (%d = pg_catalog.length('%s'))"\
759 " (SELECT conrelid FROM pg_catalog.pg_constraint "\
760 " WHERE pg_catalog.quote_ident(conname)='%s')"
762 /* the silly-looking length condition is just to eat up the current word */
763 #define Query_for_rule_of_table \
764 "SELECT pg_catalog.quote_ident(rulename) "\
765 " FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
766 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
767 " and pg_catalog.quote_ident(c1.relname)='%s'"\
768 " and pg_catalog.pg_table_is_visible(c1.oid)"
770 /* the silly-looking length condition is just to eat up the current word */
771 #define Query_for_list_of_tables_for_rule \
772 "SELECT pg_catalog.quote_ident(relname) "\
773 " FROM pg_catalog.pg_class"\
774 " WHERE (%d = pg_catalog.length('%s'))"\
776 " (SELECT ev_class FROM pg_catalog.pg_rewrite "\
777 " WHERE pg_catalog.quote_ident(rulename)='%s')"
779 /* the silly-looking length condition is just to eat up the current word */
780 #define Query_for_trigger_of_table \
781 "SELECT pg_catalog.quote_ident(tgname) "\
782 " FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
783 " WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
784 " and pg_catalog.quote_ident(c1.relname)='%s'"\
785 " and pg_catalog.pg_table_is_visible(c1.oid)"\
786 " and not tgisinternal"
788 /* the silly-looking length condition is just to eat up the current word */
789 #define Query_for_list_of_tables_for_trigger \
790 "SELECT pg_catalog.quote_ident(relname) "\
791 " FROM pg_catalog.pg_class"\
792 " WHERE (%d = pg_catalog.length('%s'))"\
794 " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
795 " WHERE pg_catalog.quote_ident(tgname)='%s')"
797 #define Query_for_list_of_ts_configurations \
798 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
799 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
801 #define Query_for_list_of_ts_dictionaries \
802 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
803 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
805 #define Query_for_list_of_ts_parsers \
806 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
807 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
809 #define Query_for_list_of_ts_templates \
810 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
811 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
813 #define Query_for_list_of_fdws \
814 " SELECT pg_catalog.quote_ident(fdwname) "\
815 " FROM pg_catalog.pg_foreign_data_wrapper "\
816 " WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
818 #define Query_for_list_of_servers \
819 " SELECT pg_catalog.quote_ident(srvname) "\
820 " FROM pg_catalog.pg_foreign_server "\
821 " WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
823 #define Query_for_list_of_user_mappings \
824 " SELECT pg_catalog.quote_ident(usename) "\
825 " FROM pg_catalog.pg_user_mappings "\
826 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
828 #define Query_for_list_of_access_methods \
829 " SELECT pg_catalog.quote_ident(amname) "\
830 " FROM pg_catalog.pg_am "\
831 " WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
833 /* the silly-looking length condition is just to eat up the current word */
834 #define Query_for_list_of_arguments \
835 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
836 " FROM pg_catalog.pg_proc "\
837 " WHERE (%d = pg_catalog.length('%s'))"\
838 " AND (pg_catalog.quote_ident(proname)='%s'"\
839 " OR '\"' || proname || '\"'='%s') "\
840 " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
842 /* the silly-looking length condition is just to eat up the current word */
843 #define Query_for_list_of_arguments_with_schema \
844 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
845 " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
846 " WHERE (%d = pg_catalog.length('%s'))"\
847 " AND n.oid = p.pronamespace "\
848 " AND (pg_catalog.quote_ident(proname)='%s' "\
849 " OR '\"' || proname || '\"' ='%s') "\
850 " AND (pg_catalog.quote_ident(nspname)='%s' "\
851 " OR '\"' || nspname || '\"' ='%s') "
853 #define Query_for_list_of_extensions \
854 " SELECT pg_catalog.quote_ident(extname) "\
855 " FROM pg_catalog.pg_extension "\
856 " WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
858 #define Query_for_list_of_available_extensions \
859 " SELECT pg_catalog.quote_ident(name) "\
860 " FROM pg_catalog.pg_available_extensions "\
861 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
863 /* the silly-looking length condition is just to eat up the current word */
864 #define Query_for_list_of_available_extension_versions \
865 " SELECT pg_catalog.quote_ident(version) "\
866 " FROM pg_catalog.pg_available_extension_versions "\
867 " WHERE (%d = pg_catalog.length('%s'))"\
868 " AND pg_catalog.quote_ident(name)='%s'"
870 /* the silly-looking length condition is just to eat up the current word */
871 #define Query_for_list_of_available_extension_versions_with_TO \
872 " SELECT 'TO ' || pg_catalog.quote_ident(version) "\
873 " FROM pg_catalog.pg_available_extension_versions "\
874 " WHERE (%d = pg_catalog.length('%s'))"\
875 " AND pg_catalog.quote_ident(name)='%s'"
877 #define Query_for_list_of_prepared_statements \
878 " SELECT pg_catalog.quote_ident(name) "\
879 " FROM pg_catalog.pg_prepared_statements "\
880 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
882 #define Query_for_list_of_event_triggers \
883 " SELECT pg_catalog.quote_ident(evtname) "\
884 " FROM pg_catalog.pg_event_trigger "\
885 " WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
887 #define Query_for_list_of_tablesample_methods \
888 " SELECT pg_catalog.quote_ident(proname) "\
889 " FROM pg_catalog.pg_proc "\
890 " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
891 " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
892 " substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
894 #define Query_for_list_of_policies \
895 " SELECT pg_catalog.quote_ident(polname) "\
896 " FROM pg_catalog.pg_policy "\
897 " WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
899 #define Query_for_list_of_tables_for_policy \
900 "SELECT pg_catalog.quote_ident(relname) "\
901 " FROM pg_catalog.pg_class"\
902 " WHERE (%d = pg_catalog.length('%s'))"\
904 " (SELECT polrelid FROM pg_catalog.pg_policy "\
905 " WHERE pg_catalog.quote_ident(polname)='%s')"
907 #define Query_for_enum \
908 " SELECT name FROM ( "\
909 " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
910 " FROM pg_catalog.pg_settings "\
911 " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
913 " SELECT 'DEFAULT' ) ss "\
914 " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
917 * This is a list of all "things" in Pgsql, which can show up after CREATE or
918 * DROP; and there is also a query to get a list of them.
924 const char *query; /* simple query, or NULL */
925 const SchemaQuery *squery; /* schema query, or NULL */
926 const bits32 flags; /* visibility flags, see below */
929 #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
930 #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
931 #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP)
933 static const pgsql_thing_t words_after_create[] = {
934 {"ACCESS METHOD", NULL, NULL},
935 {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
936 {"CAST", NULL, NULL}, /* Casts have complex structures for names, so
938 {"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'"},
941 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
942 * to be used only by pg_dump.
944 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
945 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
946 {"DATABASE", Query_for_list_of_databases},
947 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
948 {"DOMAIN", NULL, &Query_for_list_of_domains},
949 {"EVENT TRIGGER", NULL, NULL},
950 {"EXTENSION", Query_for_list_of_extensions},
951 {"FOREIGN DATA WRAPPER", NULL, NULL},
952 {"FOREIGN TABLE", NULL, NULL},
953 {"FUNCTION", NULL, &Query_for_list_of_functions},
954 {"GROUP", Query_for_list_of_roles},
955 {"LANGUAGE", Query_for_list_of_languages},
956 {"INDEX", NULL, &Query_for_list_of_indexes},
957 {"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
958 {"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a
960 {"OWNED", NULL, NULL, THING_NO_CREATE}, /* for DROP OWNED BY ... */
961 {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
962 {"POLICY", NULL, NULL},
963 {"ROLE", Query_for_list_of_roles},
964 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
965 {"SCHEMA", Query_for_list_of_schemas},
966 {"SEQUENCE", NULL, &Query_for_list_of_sequences},
967 {"SERVER", Query_for_list_of_servers},
968 {"TABLE", NULL, &Query_for_list_of_tables},
969 {"TABLESPACE", Query_for_list_of_tablespaces},
970 {"TEMP", NULL, NULL, THING_NO_DROP}, /* for CREATE TEMP TABLE ... */
971 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
972 {"TEXT SEARCH", NULL, NULL},
973 {"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"},
974 {"TYPE", NULL, &Query_for_list_of_datatypes},
975 {"UNIQUE", NULL, NULL, THING_NO_DROP}, /* for CREATE UNIQUE INDEX ... */
976 {"UNLOGGED", NULL, NULL, THING_NO_DROP}, /* for CREATE UNLOGGED TABLE
978 {"USER", Query_for_list_of_roles},
979 {"USER MAPPING FOR", NULL, NULL},
980 {"VIEW", NULL, &Query_for_list_of_views},
981 {NULL} /* end of list */
985 /* Forward declaration of functions */
986 static char **psql_completion(const char *text, int start, int end);
987 static char *create_command_generator(const char *text, int state);
988 static char *drop_command_generator(const char *text, int state);
989 static char *complete_from_query(const char *text, int state);
990 static char *complete_from_schema_query(const char *text, int state);
991 static char *_complete_from_query(int is_schema_query,
992 const char *text, int state);
993 static char *complete_from_list(const char *text, int state);
994 static char *complete_from_const(const char *text, int state);
995 static void append_variable_names(char ***varnames, int *nvars,
996 int *maxvars, const char *varname,
997 const char *prefix, const char *suffix);
998 static char **complete_from_variables(const char *text,
999 const char *prefix, const char *suffix, bool need_value);
1000 static char *complete_from_files(const char *text, int state);
1002 static char *pg_strdup_keyword_case(const char *s, const char *ref);
1003 static char *escape_string(const char *text);
1004 static PGresult *exec_query(const char *query);
1006 static char **get_previous_words(int point, char **buffer, int *nwords);
1008 static char *get_guctype(const char *varname);
1011 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
1012 static char *dequote_file_name(char *text, char quote_char);
1017 * Initialize the readline library for our purposes.
1020 initialize_readline(void)
1022 rl_readline_name = (char *) pset.progname;
1023 rl_attempted_completion_function = psql_completion;
1025 rl_basic_word_break_characters = WORD_BREAKS;
1027 completion_max_records = 1000;
1030 * There is a variable rl_completion_query_items for this but apparently
1031 * it's not defined everywhere.
1036 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1037 * using case-insensitive or case-sensitive comparisons.
1039 * If pattern is NULL, it's a wild card that matches any word.
1040 * If pattern begins with '!', the result is negated, ie we check that 'word'
1041 * does *not* match any alternative appearing in the rest of 'pattern'.
1042 * Any alternative can end with '*' which is a wild card, i.e., it means
1043 * match any word that matches the characters so far. (We do not currently
1044 * support '*' elsewhere than the end of an alternative.)
1046 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1047 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1048 * just be written directly in patterns.)
1050 #define MatchAny NULL
1051 #define MatchAnyExcept(pattern) ("!" pattern)
1054 word_matches_internal(const char *pattern,
1056 bool case_sensitive)
1061 /* NULL pattern matches anything. */
1062 if (pattern == NULL)
1065 /* Handle negated patterns from the MatchAnyExcept macro. */
1066 if (*pattern == '!')
1067 return !word_matches_internal(pattern + 1, word, case_sensitive);
1069 /* Else consider each alternative in the pattern. */
1070 wordlen = strlen(word);
1075 /* Find end of current alternative. */
1077 while (*c != '\0' && *c != '|')
1079 /* Was there a wild card? (Assumes first alternative is not empty) */
1082 /* Yes, wildcard match? */
1083 patternlen = c - pattern - 1;
1084 if (wordlen >= patternlen &&
1086 strncmp(word, pattern, patternlen) == 0 :
1087 pg_strncasecmp(word, pattern, patternlen) == 0))
1092 /* No, plain match? */
1093 patternlen = c - pattern;
1094 if (wordlen == patternlen &&
1096 strncmp(word, pattern, wordlen) == 0 :
1097 pg_strncasecmp(word, pattern, wordlen) == 0))
1100 /* Out of alternatives? */
1103 /* Nope, try next alternative. */
1111 * There are enough matching calls below that it seems worth having these two
1112 * interface routines rather than including a third parameter in every call.
1114 * word_matches --- match case-insensitively.
1117 word_matches(const char *pattern, const char *word)
1119 return word_matches_internal(pattern, word, false);
1123 * word_matches_cs --- match case-sensitively.
1126 word_matches_cs(const char *pattern, const char *word)
1128 return word_matches_internal(pattern, word, true);
1132 * Check if the final character of 's' is 'c'.
1135 ends_with(const char *s, char c)
1137 size_t length = strlen(s);
1139 return (length > 0 && s[length - 1] == c);
1143 * The completion function.
1145 * According to readline spec this gets passed the text entered so far and its
1146 * start and end positions in the readline buffer. The return value is some
1147 * partially obscure list format that can be generated by readline's
1148 * completion_matches() function, so we don't have to worry about it.
1151 psql_completion(const char *text, int start, int end)
1153 /* This is the variable we'll return. */
1154 char **matches = NULL;
1156 /* Workspace for parsed words. */
1159 /* This array will contain pointers to parsed words. */
1160 char **previous_words;
1162 /* The number of words found on the input line. */
1163 int previous_words_count;
1166 * For compactness, we use these macros to reference previous_words[].
1167 * Caution: do not access a previous_words[] entry without having checked
1168 * previous_words_count to be sure it's valid. In most cases below, that
1169 * check is implicit in a TailMatches() or similar macro, but in some
1170 * places we have to check it explicitly.
1172 #define prev_wd (previous_words[0])
1173 #define prev2_wd (previous_words[1])
1174 #define prev3_wd (previous_words[2])
1175 #define prev4_wd (previous_words[3])
1176 #define prev5_wd (previous_words[4])
1177 #define prev6_wd (previous_words[5])
1178 #define prev7_wd (previous_words[6])
1179 #define prev8_wd (previous_words[7])
1180 #define prev9_wd (previous_words[8])
1182 /* Macros for matching the last N words before point, case-insensitively. */
1183 #define TailMatches1(p1) \
1184 (previous_words_count >= 1 && \
1185 word_matches(p1, prev_wd))
1187 #define TailMatches2(p2, p1) \
1188 (previous_words_count >= 2 && \
1189 word_matches(p1, prev_wd) && \
1190 word_matches(p2, prev2_wd))
1192 #define TailMatches3(p3, p2, p1) \
1193 (previous_words_count >= 3 && \
1194 word_matches(p1, prev_wd) && \
1195 word_matches(p2, prev2_wd) && \
1196 word_matches(p3, prev3_wd))
1198 #define TailMatches4(p4, p3, p2, p1) \
1199 (previous_words_count >= 4 && \
1200 word_matches(p1, prev_wd) && \
1201 word_matches(p2, prev2_wd) && \
1202 word_matches(p3, prev3_wd) && \
1203 word_matches(p4, prev4_wd))
1205 #define TailMatches5(p5, p4, p3, p2, p1) \
1206 (previous_words_count >= 5 && \
1207 word_matches(p1, prev_wd) && \
1208 word_matches(p2, prev2_wd) && \
1209 word_matches(p3, prev3_wd) && \
1210 word_matches(p4, prev4_wd) && \
1211 word_matches(p5, prev5_wd))
1213 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1214 (previous_words_count >= 6 && \
1215 word_matches(p1, prev_wd) && \
1216 word_matches(p2, prev2_wd) && \
1217 word_matches(p3, prev3_wd) && \
1218 word_matches(p4, prev4_wd) && \
1219 word_matches(p5, prev5_wd) && \
1220 word_matches(p6, prev6_wd))
1222 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1223 (previous_words_count >= 7 && \
1224 word_matches(p1, prev_wd) && \
1225 word_matches(p2, prev2_wd) && \
1226 word_matches(p3, prev3_wd) && \
1227 word_matches(p4, prev4_wd) && \
1228 word_matches(p5, prev5_wd) && \
1229 word_matches(p6, prev6_wd) && \
1230 word_matches(p7, prev7_wd))
1232 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1233 (previous_words_count >= 8 && \
1234 word_matches(p1, prev_wd) && \
1235 word_matches(p2, prev2_wd) && \
1236 word_matches(p3, prev3_wd) && \
1237 word_matches(p4, prev4_wd) && \
1238 word_matches(p5, prev5_wd) && \
1239 word_matches(p6, prev6_wd) && \
1240 word_matches(p7, prev7_wd) && \
1241 word_matches(p8, prev8_wd))
1243 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1244 (previous_words_count >= 9 && \
1245 word_matches(p1, prev_wd) && \
1246 word_matches(p2, prev2_wd) && \
1247 word_matches(p3, prev3_wd) && \
1248 word_matches(p4, prev4_wd) && \
1249 word_matches(p5, prev5_wd) && \
1250 word_matches(p6, prev6_wd) && \
1251 word_matches(p7, prev7_wd) && \
1252 word_matches(p8, prev8_wd) && \
1253 word_matches(p9, prev9_wd))
1255 /* Macros for matching the last N words before point, case-sensitively. */
1256 #define TailMatchesCS1(p1) \
1257 (previous_words_count >= 1 && \
1258 word_matches_cs(p1, prev_wd))
1259 #define TailMatchesCS2(p2, p1) \
1260 (previous_words_count >= 2 && \
1261 word_matches_cs(p1, prev_wd) && \
1262 word_matches_cs(p2, prev2_wd))
1265 * Macros for matching N words beginning at the start of the line,
1266 * case-insensitively.
1268 #define Matches1(p1) \
1269 (previous_words_count == 1 && \
1271 #define Matches2(p1, p2) \
1272 (previous_words_count == 2 && \
1273 TailMatches2(p1, p2))
1274 #define Matches3(p1, p2, p3) \
1275 (previous_words_count == 3 && \
1276 TailMatches3(p1, p2, p3))
1277 #define Matches4(p1, p2, p3, p4) \
1278 (previous_words_count == 4 && \
1279 TailMatches4(p1, p2, p3, p4))
1280 #define Matches5(p1, p2, p3, p4, p5) \
1281 (previous_words_count == 5 && \
1282 TailMatches5(p1, p2, p3, p4, p5))
1283 #define Matches6(p1, p2, p3, p4, p5, p6) \
1284 (previous_words_count == 6 && \
1285 TailMatches6(p1, p2, p3, p4, p5, p6))
1286 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1287 (previous_words_count == 7 && \
1288 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1289 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1290 (previous_words_count == 8 && \
1291 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1292 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1293 (previous_words_count == 9 && \
1294 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1297 * Macros for matching N words at the start of the line, regardless of
1298 * what is after them, case-insensitively.
1300 #define HeadMatches1(p1) \
1301 (previous_words_count >= 1 && \
1302 word_matches(p1, previous_words[previous_words_count - 1]))
1304 #define HeadMatches2(p1, p2) \
1305 (previous_words_count >= 2 && \
1306 word_matches(p1, previous_words[previous_words_count - 1]) && \
1307 word_matches(p2, previous_words[previous_words_count - 2]))
1309 #define HeadMatches3(p1, p2, p3) \
1310 (previous_words_count >= 3 && \
1311 word_matches(p1, previous_words[previous_words_count - 1]) && \
1312 word_matches(p2, previous_words[previous_words_count - 2]) && \
1313 word_matches(p3, previous_words[previous_words_count - 3]))
1315 /* Known command-starting keywords. */
1316 static const char *const sql_commands[] = {
1317 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
1318 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1319 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1320 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1321 "MOVE", "NOTIFY", "PREPARE",
1322 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1323 "RESET", "REVOKE", "ROLLBACK",
1324 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1325 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1329 /* psql's backslash commands. */
1330 static const char *const backslash_commands[] = {
1331 "\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1332 "\\copyright", "\\crosstabview",
1333 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1334 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1335 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1336 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
1337 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1338 "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
1339 "\\f", "\\g", "\\gexec", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
1340 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1341 "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
1342 "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t", "\\T",
1343 "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL
1346 (void) end; /* "end" is not used */
1348 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1349 rl_completion_append_character = ' ';
1352 /* Clear a few things. */
1353 completion_charp = NULL;
1354 completion_charpp = NULL;
1355 completion_info_charp = NULL;
1356 completion_info_charp2 = NULL;
1359 * Scan the input line to extract the words before our current position.
1360 * According to those we'll make some smart decisions on what the user is
1361 * probably intending to type.
1363 previous_words = get_previous_words(start,
1365 &previous_words_count);
1367 /* If current word is a backslash command, offer completions for that */
1368 if (text[0] == '\\')
1369 COMPLETE_WITH_LIST_CS(backslash_commands);
1371 /* If current word is a variable interpolation, handle that case */
1372 else if (text[0] == ':' && text[1] != ':')
1374 if (text[1] == '\'')
1375 matches = complete_from_variables(text, ":'", "'", true);
1376 else if (text[1] == '"')
1377 matches = complete_from_variables(text, ":\"", "\"", true);
1379 matches = complete_from_variables(text, ":", "", true);
1382 /* If no previous word, suggest one of the basic sql commands */
1383 else if (previous_words_count == 0)
1384 COMPLETE_WITH_LIST(sql_commands);
1387 /* complete with something you can create */
1388 else if (TailMatches1("CREATE"))
1389 matches = completion_matches(text, create_command_generator);
1391 /* DROP, but not DROP embedded in other commands */
1392 /* complete with something you can drop */
1393 else if (Matches1("DROP"))
1394 matches = completion_matches(text, drop_command_generator);
1399 else if (Matches2("ALTER", "TABLE"))
1400 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1401 "UNION SELECT 'ALL IN TABLESPACE'");
1403 /* ALTER something */
1404 else if (Matches1("ALTER"))
1406 static const char *const list_ALTER[] =
1407 {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
1408 "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
1409 "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR",
1410 "POLICY", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM", "TABLE",
1411 "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
1412 "USER", "USER MAPPING FOR", "VIEW", NULL};
1414 COMPLETE_WITH_LIST(list_ALTER);
1416 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1417 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1418 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1419 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1420 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1421 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1422 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1423 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1424 COMPLETE_WITH_CONST("SET TABLESPACE");
1425 /* ALTER AGGREGATE,FUNCTION <name> */
1426 else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1427 COMPLETE_WITH_CONST("(");
1428 /* ALTER AGGREGATE,FUNCTION <name> (...) */
1429 else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1431 if (ends_with(prev_wd, ')'))
1432 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1434 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1437 /* ALTER SCHEMA <name> */
1438 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1439 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1441 /* ALTER COLLATION <name> */
1442 else if (Matches3("ALTER", "COLLATION", MatchAny))
1443 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1445 /* ALTER CONVERSION <name> */
1446 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1447 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1449 /* ALTER DATABASE <name> */
1450 else if (Matches3("ALTER", "DATABASE", MatchAny))
1451 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1452 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1453 "CONNECTION LIMIT");
1455 /* ALTER EVENT TRIGGER */
1456 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1457 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1459 /* ALTER EVENT TRIGGER <name> */
1460 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1461 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1463 /* ALTER EVENT TRIGGER <name> ENABLE */
1464 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1465 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1467 /* ALTER EXTENSION <name> */
1468 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1469 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1471 /* ALTER EXTENSION <name> UPDATE */
1472 else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
1474 completion_info_charp = prev2_wd;
1475 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
1478 /* ALTER EXTENSION <name> UPDATE TO */
1479 else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
1481 completion_info_charp = prev3_wd;
1482 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
1486 else if (Matches2("ALTER", "FOREIGN"))
1487 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1489 /* ALTER FOREIGN DATA WRAPPER <name> */
1490 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1491 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1493 /* ALTER FOREIGN TABLE <name> */
1494 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1496 static const char *const list_ALTER_FOREIGN_TABLE[] =
1497 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1498 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1499 "VALIDATE CONSTRAINT", NULL};
1501 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1505 else if (Matches2("ALTER", "INDEX"))
1506 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1507 "UNION SELECT 'ALL IN TABLESPACE'");
1508 /* ALTER INDEX <name> */
1509 else if (Matches3("ALTER", "INDEX", MatchAny))
1510 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1511 /* ALTER INDEX <name> SET */
1512 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1513 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1514 /* ALTER INDEX <name> RESET */
1515 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1516 COMPLETE_WITH_CONST("(");
1517 /* ALTER INDEX <foo> SET|RESET ( */
1518 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1519 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1520 "gin_pending_list_limit");
1521 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1522 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1523 "gin_pending_list_limit =");
1525 /* ALTER LANGUAGE <name> */
1526 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1527 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1529 /* ALTER LARGE OBJECT <oid> */
1530 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1531 COMPLETE_WITH_CONST("OWNER TO");
1533 /* ALTER MATERIALIZED VIEW */
1534 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1535 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1536 "UNION SELECT 'ALL IN TABLESPACE'");
1538 /* ALTER USER,ROLE <name> */
1539 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1540 !TailMatches2("USER", "MAPPING"))
1542 static const char *const list_ALTERUSER[] =
1543 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1544 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1545 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1546 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1547 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1548 "VALID UNTIL", "WITH", NULL};
1550 COMPLETE_WITH_LIST(list_ALTERUSER);
1553 /* ALTER USER,ROLE <name> WITH */
1554 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1556 /* Similar to the above, but don't complete "WITH" again. */
1557 static const char *const list_ALTERUSER_WITH[] =
1558 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1559 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1560 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1561 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1562 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1563 "VALID UNTIL", NULL};
1565 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1568 /* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
1569 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
1570 COMPLETE_WITH_CONST("PASSWORD");
1571 /* ALTER DEFAULT PRIVILEGES */
1572 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1573 COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
1574 /* ALTER DEFAULT PRIVILEGES FOR */
1575 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1576 COMPLETE_WITH_CONST("ROLE");
1577 /* ALTER DEFAULT PRIVILEGES IN */
1578 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1579 COMPLETE_WITH_CONST("SCHEMA");
1580 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1581 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1583 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
1584 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1585 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1587 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
1588 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1589 else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1591 COMPLETE_WITH_CONST("ROLE");
1592 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
1593 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1594 else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1595 MatchAny, "IN", "SCHEMA", MatchAny) ||
1596 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1597 MatchAny, "FOR", "ROLE|USER", MatchAny))
1598 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1599 /* ALTER DOMAIN <name> */
1600 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1601 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1602 "VALIDATE CONSTRAINT");
1603 /* ALTER DOMAIN <sth> DROP */
1604 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1605 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1606 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1607 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1609 completion_info_charp = prev3_wd;
1610 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1612 /* ALTER DOMAIN <sth> RENAME */
1613 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1614 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1615 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1616 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1617 COMPLETE_WITH_CONST("TO");
1619 /* ALTER DOMAIN <sth> SET */
1620 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1621 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1622 /* ALTER SEQUENCE <name> */
1623 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1625 static const char *const list_ALTERSEQUENCE[] =
1626 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1627 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1629 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1631 /* ALTER SEQUENCE <name> NO */
1632 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1633 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1634 /* ALTER SERVER <name> */
1635 else if (Matches3("ALTER", "SERVER", MatchAny))
1636 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1637 /* ALTER SERVER <name> VERSION <version> */
1638 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1639 COMPLETE_WITH_CONST("OPTIONS");
1640 /* ALTER SYSTEM SET, RESET, RESET ALL */
1641 else if (Matches2("ALTER", "SYSTEM"))
1642 COMPLETE_WITH_LIST2("SET", "RESET");
1643 /* ALTER SYSTEM SET|RESET <name> */
1644 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1645 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1646 /* ALTER VIEW <name> */
1647 else if (Matches3("ALTER", "VIEW", MatchAny))
1648 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1650 /* ALTER MATERIALIZED VIEW <name> */
1651 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1652 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1655 /* ALTER POLICY <name> */
1656 else if (Matches2("ALTER", "POLICY"))
1657 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1658 /* ALTER POLICY <name> ON */
1659 else if (Matches3("ALTER", "POLICY", MatchAny))
1660 COMPLETE_WITH_CONST("ON");
1661 /* ALTER POLICY <name> ON <table> */
1662 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1664 completion_info_charp = prev2_wd;
1665 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1667 /* ALTER POLICY <name> ON <table> - show options */
1668 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1669 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1670 /* ALTER POLICY <name> ON <table> TO <role> */
1671 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1672 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1673 /* ALTER POLICY <name> ON <table> USING ( */
1674 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1675 COMPLETE_WITH_CONST("(");
1676 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1677 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1678 COMPLETE_WITH_CONST("(");
1680 /* ALTER RULE <name>, add ON */
1681 else if (Matches3("ALTER", "RULE", MatchAny))
1682 COMPLETE_WITH_CONST("ON");
1684 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1685 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1687 completion_info_charp = prev2_wd;
1688 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1691 /* ALTER RULE <name> ON <name> */
1692 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1693 COMPLETE_WITH_CONST("RENAME TO");
1695 /* ALTER TRIGGER <name>, add ON */
1696 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1697 COMPLETE_WITH_CONST("ON");
1699 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1701 completion_info_charp = prev2_wd;
1702 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1706 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1708 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1709 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1711 /* ALTER TRIGGER <name> ON <name> */
1712 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1713 COMPLETE_WITH_CONST("RENAME TO");
1716 * If we detect ALTER TABLE <name>, suggest sub commands
1718 else if (Matches3("ALTER", "TABLE", MatchAny))
1720 static const char *const list_ALTER2[] =
1721 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1722 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1723 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", NULL};
1725 COMPLETE_WITH_LIST(list_ALTER2);
1727 /* ALTER TABLE xxx ENABLE */
1728 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1729 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1731 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1732 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1733 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1735 completion_info_charp = prev3_wd;
1736 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1738 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1740 completion_info_charp = prev4_wd;
1741 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1743 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1745 completion_info_charp = prev3_wd;
1746 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1748 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1750 completion_info_charp = prev4_wd;
1751 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1753 /* ALTER TABLE xxx INHERIT */
1754 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1755 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1756 /* ALTER TABLE xxx NO INHERIT */
1757 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1758 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1759 /* ALTER TABLE xxx DISABLE */
1760 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1761 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1762 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1764 completion_info_charp = prev3_wd;
1765 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1767 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1769 completion_info_charp = prev3_wd;
1770 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1773 /* ALTER TABLE xxx ALTER */
1774 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1775 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1777 /* ALTER TABLE xxx RENAME */
1778 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1779 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1780 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1781 COMPLETE_WITH_ATTR(prev3_wd, "");
1783 /* ALTER TABLE xxx RENAME yyy */
1784 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1785 COMPLETE_WITH_CONST("TO");
1787 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1788 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1789 COMPLETE_WITH_CONST("TO");
1791 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1792 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1793 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1794 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1795 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1796 COMPLETE_WITH_ATTR(prev3_wd, "");
1799 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1800 * provide list of constraints
1802 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1804 completion_info_charp = prev3_wd;
1805 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1807 /* ALTER TABLE ALTER [COLUMN] <foo> */
1808 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1809 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1810 COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
1811 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1812 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1813 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1814 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1815 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1816 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1817 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1818 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1819 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1820 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1821 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1822 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1823 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1824 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1825 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1826 COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
1827 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1828 COMPLETE_WITH_CONST("ON");
1829 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1831 completion_info_charp = prev3_wd;
1832 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1834 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1835 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1836 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1840 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1843 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1844 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1845 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
1846 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
1847 COMPLETE_WITH_CONST("OIDS");
1848 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1849 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1850 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
1851 /* ALTER TABLE <foo> RESET */
1852 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
1853 COMPLETE_WITH_CONST("(");
1854 /* ALTER TABLE <foo> SET|RESET ( */
1855 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1857 static const char *const list_TABLEOPTIONS[] =
1859 "autovacuum_analyze_scale_factor",
1860 "autovacuum_analyze_threshold",
1861 "autovacuum_enabled",
1862 "autovacuum_freeze_max_age",
1863 "autovacuum_freeze_min_age",
1864 "autovacuum_freeze_table_age",
1865 "autovacuum_multixact_freeze_max_age",
1866 "autovacuum_multixact_freeze_min_age",
1867 "autovacuum_multixact_freeze_table_age",
1868 "autovacuum_vacuum_cost_delay",
1869 "autovacuum_vacuum_cost_limit",
1870 "autovacuum_vacuum_scale_factor",
1871 "autovacuum_vacuum_threshold",
1874 "log_autovacuum_min_duration",
1875 "toast.autovacuum_enabled",
1876 "toast.autovacuum_freeze_max_age",
1877 "toast.autovacuum_freeze_min_age",
1878 "toast.autovacuum_freeze_table_age",
1879 "toast.autovacuum_multixact_freeze_max_age",
1880 "toast.autovacuum_multixact_freeze_min_age",
1881 "toast.autovacuum_multixact_freeze_table_age",
1882 "toast.autovacuum_vacuum_cost_delay",
1883 "toast.autovacuum_vacuum_cost_limit",
1884 "toast.autovacuum_vacuum_scale_factor",
1885 "toast.autovacuum_vacuum_threshold",
1886 "toast.log_autovacuum_min_duration",
1887 "user_catalog_table",
1891 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
1893 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
1895 completion_info_charp = prev5_wd;
1896 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1898 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1899 COMPLETE_WITH_CONST("INDEX");
1900 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1901 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
1902 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
1903 COMPLETE_WITH_CONST("IDENTITY");
1905 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
1906 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
1907 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
1908 /* ALTER TABLESPACE <foo> SET|RESET */
1909 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
1910 COMPLETE_WITH_CONST("(");
1911 /* ALTER TABLESPACE <foo> SET|RESET ( */
1912 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
1913 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
1914 "effective_io_concurrency");
1916 /* ALTER TEXT SEARCH */
1917 else if (Matches3("ALTER", "TEXT", "SEARCH"))
1918 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1919 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
1920 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
1921 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
1922 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1923 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
1924 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
1926 "OWNER TO", "RENAME TO", "SET SCHEMA");
1928 /* complete ALTER TYPE <foo> with actions */
1929 else if (Matches3("ALTER", "TYPE", MatchAny))
1930 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
1932 "OWNER TO", "RENAME", "SET SCHEMA");
1933 /* complete ALTER TYPE <foo> ADD with actions */
1934 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
1935 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
1936 /* ALTER TYPE <foo> RENAME */
1937 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
1938 COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
1939 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
1940 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
1941 COMPLETE_WITH_CONST("TO");
1943 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
1946 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
1947 COMPLETE_WITH_ATTR(prev3_wd, "");
1948 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
1949 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
1950 COMPLETE_WITH_CONST("TYPE");
1951 /* complete ALTER GROUP <foo> */
1952 else if (Matches3("ALTER", "GROUP", MatchAny))
1953 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
1954 /* complete ALTER GROUP <foo> ADD|DROP with USER */
1955 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
1956 COMPLETE_WITH_CONST("USER");
1957 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
1958 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
1959 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1962 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
1964 else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
1965 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
1968 else if (Matches1("BEGIN"))
1969 COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
1971 else if (Matches1("END|ABORT"))
1972 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
1974 else if (Matches1("COMMIT"))
1975 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
1976 /* RELEASE SAVEPOINT */
1977 else if (Matches1("RELEASE"))
1978 COMPLETE_WITH_CONST("SAVEPOINT");
1980 else if (Matches1("ROLLBACK"))
1981 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
1983 else if (Matches1("CLUSTER"))
1984 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
1985 else if (Matches2("CLUSTER", "VERBOSE"))
1986 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
1987 /* If we have CLUSTER <sth>, then add "USING" */
1988 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
1989 COMPLETE_WITH_CONST("USING");
1990 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
1991 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
1992 COMPLETE_WITH_CONST("USING");
1993 /* If we have CLUSTER <sth> USING, then add the index as well */
1994 else if (Matches3("CLUSTER", MatchAny, "USING") ||
1995 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
1997 completion_info_charp = prev2_wd;
1998 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2002 else if (Matches1("COMMENT"))
2003 COMPLETE_WITH_CONST("ON");
2004 else if (Matches2("COMMENT", "ON"))
2006 static const char *const list_COMMENT[] =
2007 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
2008 "EVENT TRIGGER", "EXTENSION",
2009 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2010 "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
2011 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
2012 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
2013 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
2015 COMPLETE_WITH_LIST(list_COMMENT);
2017 else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
2018 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2019 else if (Matches3("COMMENT", "ON", "FOREIGN"))
2020 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2021 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
2022 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2023 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
2024 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
2025 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
2026 COMPLETE_WITH_CONST("ON");
2027 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2029 completion_info_charp = prev2_wd;
2030 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
2032 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
2033 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2034 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
2035 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2036 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
2037 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2038 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
2039 COMPLETE_WITH_CONST("IS");
2044 * If we have COPY, offer list of tables or "(" (Also cover the analogous
2045 * backslash command).
2047 else if (Matches1("COPY|\\copy"))
2048 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2049 " UNION ALL SELECT '('");
2050 /* If we have COPY BINARY, complete with list of tables */
2051 else if (Matches2("COPY", "BINARY"))
2052 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2053 /* If we have COPY (, complete it with legal commands */
2054 else if (Matches2("COPY|\\copy", "("))
2055 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
2056 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
2057 else if (Matches2("COPY|\\copy", MatchAny) ||
2058 Matches3("COPY", "BINARY", MatchAny))
2059 COMPLETE_WITH_LIST2("FROM", "TO");
2060 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
2061 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
2062 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
2064 completion_charp = "";
2065 matches = completion_matches(text, complete_from_files);
2068 /* Handle COPY [BINARY] <sth> FROM|TO filename */
2069 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
2070 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
2071 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
2074 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
2075 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
2076 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
2077 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
2080 /* CREATE ACCESS METHOD */
2081 /* Complete "CREATE ACCESS METHOD <name>" */
2082 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
2083 COMPLETE_WITH_CONST("TYPE");
2084 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
2085 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
2086 COMPLETE_WITH_CONST("INDEX");
2087 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
2088 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
2089 COMPLETE_WITH_CONST("HANDLER");
2091 /* CREATE DATABASE */
2092 else if (Matches3("CREATE", "DATABASE", MatchAny))
2093 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2095 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2096 "LC_COLLATE", "LC_CTYPE");
2098 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2099 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2101 /* CREATE EXTENSION */
2102 /* Complete with available extensions rather than installed ones. */
2103 else if (Matches2("CREATE", "EXTENSION"))
2104 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2105 /* CREATE EXTENSION <name> */
2106 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2107 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2108 /* CREATE EXTENSION <name> VERSION */
2109 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2111 completion_info_charp = prev2_wd;
2112 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2115 /* CREATE FOREIGN */
2116 else if (Matches2("CREATE", "FOREIGN"))
2117 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2119 /* CREATE FOREIGN DATA WRAPPER */
2120 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2121 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2123 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2124 /* First off we complete CREATE UNIQUE with "INDEX" */
2125 else if (TailMatches2("CREATE", "UNIQUE"))
2126 COMPLETE_WITH_CONST("INDEX");
2129 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2132 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2133 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2134 " UNION SELECT 'ON'"
2135 " UNION SELECT 'CONCURRENTLY'");
2136 /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
2137 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2138 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2139 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2142 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2145 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2146 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2147 " UNION SELECT 'ON'");
2148 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2149 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2150 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2151 COMPLETE_WITH_CONST("ON");
2154 * Complete INDEX <name> ON <table> with a list of table columns (which
2155 * should really be in parens)
2157 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2158 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2159 COMPLETE_WITH_LIST2("(", "USING");
2160 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2161 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2162 COMPLETE_WITH_ATTR(prev2_wd, "");
2163 /* same if you put in USING */
2164 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2165 COMPLETE_WITH_ATTR(prev4_wd, "");
2166 /* Complete USING with an index method */
2167 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2168 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2169 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2170 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2171 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2172 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2173 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2174 COMPLETE_WITH_CONST("(");
2177 /* Complete "CREATE POLICY <name> ON" */
2178 else if (Matches3("CREATE", "POLICY", MatchAny))
2179 COMPLETE_WITH_CONST("ON");
2180 /* Complete "CREATE POLICY <name> ON <table>" */
2181 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2182 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2183 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
2184 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2185 COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
2186 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
2187 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
2188 COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
2189 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR|TO|USING|WITH CHECK */
2190 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
2191 COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
2192 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2193 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2194 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2195 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2196 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2197 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2198 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2199 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2200 COMPLETE_WITH_LIST2("TO", "USING (");
2201 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2202 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2203 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2204 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2205 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2206 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2207 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2208 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2209 COMPLETE_WITH_CONST("(");
2210 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2211 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
2212 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2213 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR INSERT TO|WITH CHECK" */
2214 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
2215 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2216 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR SELECT|DELETE TO|USING" */
2217 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
2218 COMPLETE_WITH_LIST2("TO", "USING (");
2219 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR ALL|UPDATE TO|USING|WITH CHECK */
2220 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
2221 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2222 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO <role>" */
2223 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
2224 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2225 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE USING (" */
2226 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
2227 COMPLETE_WITH_CONST("(");
2231 /* Complete "CREATE RULE <sth>" with "AS ON" */
2232 else if (Matches3("CREATE", "RULE", MatchAny))
2233 COMPLETE_WITH_CONST("AS ON");
2234 /* Complete "CREATE RULE <sth> AS" with "ON" */
2235 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2236 COMPLETE_WITH_CONST("ON");
2237 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2238 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2239 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2240 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2241 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2242 COMPLETE_WITH_CONST("TO");
2243 /* Complete "AS ON <sth> TO" with a table name */
2244 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2245 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2247 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2248 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2249 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2250 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2251 "CYCLE", "OWNED BY", "START WITH");
2252 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2253 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2254 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2256 /* CREATE SERVER <name> */
2257 else if (Matches3("CREATE", "SERVER", MatchAny))
2258 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2260 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2261 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2262 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2263 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2264 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2265 else if (TailMatches2("CREATE", "UNLOGGED"))
2266 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2268 /* CREATE TABLESPACE */
2269 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2270 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2271 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2272 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2273 COMPLETE_WITH_CONST("LOCATION");
2275 /* CREATE TEXT SEARCH */
2276 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2277 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2278 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2279 COMPLETE_WITH_CONST("(");
2281 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2282 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2283 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2284 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2285 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2286 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2287 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2288 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2289 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2290 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2291 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2292 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2293 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2294 COMPLETE_WITH_LIST2("ON", "OR");
2297 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2300 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2301 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2302 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2303 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2304 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2305 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
2306 COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
2307 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2308 else if (HeadMatches2("CREATE", "TRIGGER") &&
2309 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
2310 COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2311 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
2312 COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
2313 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
2314 COMPLETE_WITH_CONST("AS");
2315 else if (HeadMatches2("CREATE", "TRIGGER") &&
2316 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
2317 TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
2318 COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2319 else if (HeadMatches2("CREATE", "TRIGGER") &&
2320 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
2321 TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
2322 COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2323 else if (HeadMatches2("CREATE", "TRIGGER") &&
2324 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2325 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2326 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
2327 TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
2328 COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
2329 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
2330 COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
2331 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
2332 COMPLETE_WITH_LIST2("ROW", "STATEMENT");
2333 else if (HeadMatches2("CREATE", "TRIGGER") &&
2334 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
2335 TailMatches2("FOR", "ROW|STATEMENT")))
2336 COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
2337 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2338 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2339 COMPLETE_WITH_CONST("PROCEDURE");
2340 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
2341 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2343 /* CREATE ROLE,USER,GROUP <name> */
2344 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2345 !TailMatches2("USER", "MAPPING"))
2347 static const char *const list_CREATEROLE[] =
2348 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2349 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2350 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2351 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2352 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2353 "VALID UNTIL", "WITH", NULL};
2355 COMPLETE_WITH_LIST(list_CREATEROLE);
2358 /* CREATE ROLE,USER,GROUP <name> WITH */
2359 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2361 /* Similar to the above, but don't complete "WITH" again. */
2362 static const char *const list_CREATEROLE_WITH[] =
2363 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2364 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2365 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2366 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2367 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2368 "VALID UNTIL", NULL};
2370 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2374 * complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
2377 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
2378 COMPLETE_WITH_CONST("PASSWORD");
2379 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2380 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2381 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2383 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2384 /* Complete CREATE VIEW <name> with AS */
2385 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2386 COMPLETE_WITH_CONST("AS");
2387 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2388 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2389 COMPLETE_WITH_CONST("SELECT");
2391 /* CREATE MATERIALIZED VIEW */
2392 else if (Matches2("CREATE", "MATERIALIZED"))
2393 COMPLETE_WITH_CONST("VIEW");
2394 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2395 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2396 COMPLETE_WITH_CONST("AS");
2397 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2398 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2399 COMPLETE_WITH_CONST("SELECT");
2401 /* CREATE EVENT TRIGGER */
2402 else if (Matches2("CREATE", "EVENT"))
2403 COMPLETE_WITH_CONST("TRIGGER");
2404 /* Complete CREATE EVENT TRIGGER <name> with ON */
2405 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2406 COMPLETE_WITH_CONST("ON");
2407 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2408 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2409 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2412 else if (Matches2("DECLARE", MatchAny))
2413 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2415 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2416 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2418 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2419 /* ... despite which, only complete DELETE with FROM at start of line */
2420 else if (Matches1("DELETE"))
2421 COMPLETE_WITH_CONST("FROM");
2422 /* Complete DELETE FROM with a list of tables */
2423 else if (TailMatches2("DELETE", "FROM"))
2424 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2425 /* Complete DELETE FROM <table> */
2426 else if (TailMatches3("DELETE", "FROM", MatchAny))
2427 COMPLETE_WITH_LIST2("USING", "WHERE");
2428 /* XXX: implement tab completion for DELETE ... USING */
2431 else if (Matches1("DISCARD"))
2432 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2435 else if (Matches1("DO"))
2436 COMPLETE_WITH_CONST("LANGUAGE");
2439 /* Complete DROP object with CASCADE / RESTRICT */
2440 else if (Matches3("DROP",
2441 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
2443 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2444 (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2445 ends_with(prev_wd, ')')) ||
2446 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2447 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2448 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2449 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2450 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2452 /* help completing some of the variants */
2453 else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2454 COMPLETE_WITH_CONST("(");
2455 else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2456 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2457 else if (Matches2("DROP", "FOREIGN"))
2458 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2461 else if (Matches2("DROP", "INDEX"))
2462 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2463 " UNION SELECT 'CONCURRENTLY'");
2464 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2465 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2466 else if (Matches3("DROP", "INDEX", MatchAny))
2467 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2468 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2469 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2471 /* DROP MATERIALIZED VIEW */
2472 else if (Matches2("DROP", "MATERIALIZED"))
2473 COMPLETE_WITH_CONST("VIEW");
2474 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2475 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2478 else if (Matches2("DROP", "OWNED"))
2479 COMPLETE_WITH_CONST("BY");
2480 else if (Matches3("DROP", "OWNED", "BY"))
2481 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2483 else if (Matches3("DROP", "TEXT", "SEARCH"))
2484 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2487 else if (Matches3("DROP", "TRIGGER", MatchAny))
2488 COMPLETE_WITH_CONST("ON");
2489 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2491 completion_info_charp = prev2_wd;
2492 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2494 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2495 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2497 /* DROP ACCESS METHOD */
2498 else if (Matches2("DROP", "ACCESS"))
2499 COMPLETE_WITH_CONST("METHOD");
2500 else if (Matches3("DROP", "ACCESS", "METHOD"))
2501 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2503 /* DROP EVENT TRIGGER */
2504 else if (Matches2("DROP", "EVENT"))
2505 COMPLETE_WITH_CONST("TRIGGER");
2506 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2507 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2509 /* DROP POLICY <name> */
2510 else if (Matches2("DROP", "POLICY"))
2511 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2512 /* DROP POLICY <name> ON */
2513 else if (Matches3("DROP", "POLICY", MatchAny))
2514 COMPLETE_WITH_CONST("ON");
2515 /* DROP POLICY <name> ON <table> */
2516 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2518 completion_info_charp = prev2_wd;
2519 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2523 else if (Matches3("DROP", "RULE", MatchAny))
2524 COMPLETE_WITH_CONST("ON");
2525 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2527 completion_info_charp = prev2_wd;
2528 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2530 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2531 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2534 else if (Matches1("EXECUTE"))
2535 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2540 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2542 else if (Matches1("EXPLAIN"))
2543 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2544 "ANALYZE", "VERBOSE");
2545 else if (Matches2("EXPLAIN", "ANALYZE"))
2546 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2548 else if (Matches2("EXPLAIN", "VERBOSE") ||
2549 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2550 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2553 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2554 else if (Matches1("FETCH|MOVE"))
2555 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2556 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2557 else if (Matches2("FETCH|MOVE", MatchAny))
2558 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2561 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2562 * but we may as well tab-complete both: perhaps some users prefer one
2563 * variant or the other.
2565 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2566 COMPLETE_WITH_LIST2("FROM", "IN");
2568 /* FOREIGN DATA WRAPPER */
2569 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2570 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2571 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2572 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2573 /* applies in CREATE SERVER */
2574 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2575 HeadMatches2("CREATE", "SERVER"))
2576 COMPLETE_WITH_CONST("OPTIONS");
2579 else if (TailMatches2("FOREIGN", "TABLE") &&
2580 !TailMatches3("CREATE", MatchAny, MatchAny))
2581 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2583 /* FOREIGN SERVER */
2584 else if (TailMatches2("FOREIGN", "SERVER"))
2585 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2588 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
2589 * ALTER DEFAULT PRIVILEGES, so use TailMatches
2591 /* Complete GRANT/REVOKE with a list of roles and privileges */
2592 else if (TailMatches1("GRANT|REVOKE"))
2594 * With ALTER DEFAULT PRIVILEGES, restrict completion
2595 * to grantable privileges (can't grant roles)
2597 if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
2598 COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
2599 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
2600 "EXECUTE", "USAGE", "ALL");
2602 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2603 " UNION SELECT 'SELECT'"
2604 " UNION SELECT 'INSERT'"
2605 " UNION SELECT 'UPDATE'"
2606 " UNION SELECT 'DELETE'"
2607 " UNION SELECT 'TRUNCATE'"
2608 " UNION SELECT 'REFERENCES'"
2609 " UNION SELECT 'TRIGGER'"
2610 " UNION SELECT 'CREATE'"
2611 " UNION SELECT 'CONNECT'"
2612 " UNION SELECT 'TEMPORARY'"
2613 " UNION SELECT 'EXECUTE'"
2614 " UNION SELECT 'USAGE'"
2615 " UNION SELECT 'ALL'");
2618 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2621 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2623 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2624 COMPLETE_WITH_CONST("ON");
2625 else if (TailMatches2("GRANT", MatchAny))
2626 COMPLETE_WITH_CONST("TO");
2628 COMPLETE_WITH_CONST("FROM");
2632 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2635 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2636 * result via UNION; seems to work intuitively.
2638 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2639 * here will only work if the privilege list contains exactly one
2642 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2644 * With ALTER DEFAULT PRIVILEGES, restrict completion
2645 * to the kinds of objects supported.
2647 if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
2648 COMPLETE_WITH_LIST4("TABLES", "SEQUENCES", "FUNCTIONS", "TYPES");
2650 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2651 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2652 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2653 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2654 " UNION SELECT 'DATABASE'"
2655 " UNION SELECT 'DOMAIN'"
2656 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2657 " UNION SELECT 'FOREIGN SERVER'"
2658 " UNION SELECT 'FUNCTION'"
2659 " UNION SELECT 'LANGUAGE'"
2660 " UNION SELECT 'LARGE OBJECT'"
2661 " UNION SELECT 'SCHEMA'"
2662 " UNION SELECT 'SEQUENCE'"
2663 " UNION SELECT 'TABLE'"
2664 " UNION SELECT 'TABLESPACE'"
2665 " UNION SELECT 'TYPE'");
2667 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2668 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2669 "TABLES IN SCHEMA");
2671 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2672 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2675 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2676 * appropriate objects.
2678 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2680 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2682 if (TailMatches1("DATABASE"))
2683 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2684 else if (TailMatches1("DOMAIN"))
2685 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2686 else if (TailMatches1("FUNCTION"))
2687 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2688 else if (TailMatches1("LANGUAGE"))
2689 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2690 else if (TailMatches1("SCHEMA"))
2691 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2692 else if (TailMatches1("SEQUENCE"))
2693 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2694 else if (TailMatches1("TABLE"))
2695 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2696 else if (TailMatches1("TABLESPACE"))
2697 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2698 else if (TailMatches1("TYPE"))
2699 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2700 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2701 COMPLETE_WITH_CONST("TO");
2703 COMPLETE_WITH_CONST("FROM");
2707 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2708 * CURRENT_USER, or SESSION_USER.
2710 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2711 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2712 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2713 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
2714 else if (HeadMatches3("ALTER","DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
2715 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2716 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2717 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2718 COMPLETE_WITH_CONST("TO");
2719 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2720 COMPLETE_WITH_CONST("FROM");
2722 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2723 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2725 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2726 COMPLETE_WITH_CONST("TO");
2728 COMPLETE_WITH_CONST("FROM");
2731 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2732 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2734 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2735 COMPLETE_WITH_CONST("TO");
2737 COMPLETE_WITH_CONST("FROM");
2740 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
2741 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
2743 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2744 COMPLETE_WITH_CONST("TO");
2746 COMPLETE_WITH_CONST("FROM");
2750 else if (TailMatches3("FROM", MatchAny, "GROUP"))
2751 COMPLETE_WITH_CONST("BY");
2753 /* IMPORT FOREIGN SCHEMA */
2754 else if (Matches1("IMPORT"))
2755 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
2756 else if (Matches2("IMPORT", "FOREIGN"))
2757 COMPLETE_WITH_CONST("SCHEMA");
2759 /* INSERT --- can be inside EXPLAIN, RULE, etc */
2760 /* Complete INSERT with "INTO" */
2761 else if (TailMatches1("INSERT"))
2762 COMPLETE_WITH_CONST("INTO");
2763 /* Complete INSERT INTO with table names */
2764 else if (TailMatches2("INSERT", "INTO"))
2765 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2766 /* Complete "INSERT INTO <table> (" with attribute names */
2767 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
2768 COMPLETE_WITH_ATTR(prev2_wd, "");
2771 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2772 * "TABLE" or "DEFAULT VALUES"
2774 else if (TailMatches3("INSERT", "INTO", MatchAny))
2775 COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
2778 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
2781 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
2782 ends_with(prev_wd, ')'))
2783 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
2785 /* Insert an open parenthesis after "VALUES" */
2786 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
2787 COMPLETE_WITH_CONST("(");
2790 /* Complete LOCK [TABLE] with a list of tables */
2791 else if (Matches1("LOCK"))
2792 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2793 " UNION SELECT 'TABLE'");
2794 else if (Matches2("LOCK", "TABLE"))
2795 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2797 /* For the following, handle the case of a single table only for now */
2799 /* Complete LOCK [TABLE] <table> with "IN" */
2800 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
2801 Matches3("LOCK", "TABLE", MatchAny))
2802 COMPLETE_WITH_CONST("IN");
2804 /* Complete LOCK [TABLE] <table> IN with a lock mode */
2805 else if (Matches3("LOCK", MatchAny, "IN") ||
2806 Matches4("LOCK", "TABLE", MatchAny, "IN"))
2807 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
2808 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
2809 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
2810 "SHARE ROW EXCLUSIVE MODE",
2811 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
2813 /* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
2814 else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
2815 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
2816 COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
2818 /* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
2819 else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
2820 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
2821 COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
2822 "UPDATE EXCLUSIVE MODE");
2824 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
2825 else if (TailMatches1("NOTIFY"))
2826 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'");
2829 else if (TailMatches1("OPTIONS"))
2830 COMPLETE_WITH_CONST("(");
2832 /* OWNER TO - complete with available roles */
2833 else if (TailMatches2("OWNER", "TO"))
2834 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2837 else if (TailMatches3("FROM", MatchAny, "ORDER"))
2838 COMPLETE_WITH_CONST("BY");
2839 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
2840 COMPLETE_WITH_ATTR(prev3_wd, "");
2843 else if (Matches3("PREPARE", MatchAny, "AS"))
2844 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
2847 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
2848 * managers, not for manual use in interactive sessions.
2851 /* REASSIGN OWNED BY xxx TO yyy */
2852 else if (Matches1("REASSIGN"))
2853 COMPLETE_WITH_CONST("OWNED BY");
2854 else if (Matches2("REASSIGN", "OWNED"))
2855 COMPLETE_WITH_CONST("BY");
2856 else if (Matches3("REASSIGN", "OWNED", "BY"))
2857 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2858 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
2859 COMPLETE_WITH_CONST("TO");
2860 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
2861 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2863 /* REFRESH MATERIALIZED VIEW */
2864 else if (Matches1("REFRESH"))
2865 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
2866 else if (Matches2("REFRESH", "MATERIALIZED"))
2867 COMPLETE_WITH_CONST("VIEW");
2868 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
2869 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
2870 " UNION SELECT 'CONCURRENTLY'");
2871 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
2872 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2873 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
2874 COMPLETE_WITH_CONST("WITH");
2875 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
2876 COMPLETE_WITH_CONST("WITH");
2877 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
2878 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2879 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
2880 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2881 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
2882 COMPLETE_WITH_CONST("DATA");
2883 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
2884 COMPLETE_WITH_CONST("DATA");
2887 else if (Matches1("REINDEX"))
2888 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
2889 else if (Matches2("REINDEX", "TABLE"))
2890 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2891 else if (Matches2("REINDEX", "INDEX"))
2892 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2893 else if (Matches2("REINDEX", "SCHEMA"))
2894 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2895 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
2896 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2898 /* SECURITY LABEL */
2899 else if (Matches1("SECURITY"))
2900 COMPLETE_WITH_CONST("LABEL");
2901 else if (Matches2("SECURITY", "LABEL"))
2902 COMPLETE_WITH_LIST2("ON", "FOR");
2903 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
2904 COMPLETE_WITH_CONST("ON");
2905 else if (Matches3("SECURITY", "LABEL", "ON") ||
2906 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
2908 static const char *const list_SECURITY_LABEL[] =
2909 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
2910 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
2911 "MATERIALIZED VIEW", "LANGUAGE", "ROLE", "SCHEMA",
2912 "SEQUENCE", "TABLESPACE", "TYPE", "VIEW", NULL};
2914 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
2916 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
2917 COMPLETE_WITH_CONST("IS");
2922 /* SET, RESET, SHOW */
2923 /* Complete with a variable name */
2924 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
2925 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
2926 else if (Matches1("SHOW"))
2927 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
2928 /* Complete "SET TRANSACTION" */
2929 else if (Matches2("SET", "TRANSACTION"))
2930 COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2931 else if (Matches2("BEGIN|START", "TRANSACTION") ||
2932 Matches2("BEGIN", "WORK") ||
2933 Matches1("BEGIN") ||
2934 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
2935 COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2936 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
2937 Matches2("BEGIN", "NOT") ||
2938 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
2939 COMPLETE_WITH_CONST("DEFERRABLE");
2940 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
2941 Matches2("BEGIN", "ISOLATION") ||
2942 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
2943 COMPLETE_WITH_CONST("LEVEL");
2944 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
2945 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
2946 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
2947 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
2948 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
2949 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
2950 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
2951 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
2952 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
2953 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
2954 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
2955 COMPLETE_WITH_CONST("READ");
2956 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
2957 Matches2("BEGIN", "READ") ||
2958 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
2959 COMPLETE_WITH_LIST2("ONLY", "WRITE");
2960 /* SET CONSTRAINTS */
2961 else if (Matches2("SET", "CONSTRAINTS"))
2962 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
2963 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
2964 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
2965 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
2966 /* Complete SET ROLE */
2967 else if (Matches2("SET", "ROLE"))
2968 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2969 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
2970 else if (Matches2("SET", "SESSION"))
2971 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
2972 /* Complete SET SESSION AUTHORIZATION with username */
2973 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
2974 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
2975 /* Complete RESET SESSION with AUTHORIZATION */
2976 else if (Matches2("RESET", "SESSION"))
2977 COMPLETE_WITH_CONST("AUTHORIZATION");
2978 /* Complete SET <var> with "TO" */
2979 else if (Matches2("SET", MatchAny))
2980 COMPLETE_WITH_CONST("TO");
2981 /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
2982 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
2983 TailMatches2("SET", MatchAny))
2984 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
2985 /* Suggest possible variable values */
2986 else if (TailMatches3("SET", MatchAny, "TO|="))
2988 /* special cased code for individual GUCs */
2989 if (TailMatches2("DateStyle", "TO|="))
2991 static const char *const my_list[] =
2992 {"ISO", "SQL", "Postgres", "German",
2993 "YMD", "DMY", "MDY",
2994 "US", "European", "NonEuropean",
2997 COMPLETE_WITH_LIST(my_list);
2999 else if (TailMatches2("search_path", "TO|="))
3000 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
3001 " AND nspname not like 'pg\\_toast%%' "
3002 " AND nspname not like 'pg\\_temp%%' "
3003 " UNION SELECT 'DEFAULT' ");
3006 /* generic, type based, GUC support */
3007 char *guctype = get_guctype(prev2_wd);
3009 if (guctype && strcmp(guctype, "enum") == 0)
3011 char querybuf[1024];
3013 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
3014 COMPLETE_WITH_QUERY(querybuf);
3016 else if (guctype && strcmp(guctype, "bool") == 0)
3017 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
3018 "1", "0", "DEFAULT");
3020 COMPLETE_WITH_CONST("DEFAULT");
3027 /* START TRANSACTION */
3028 else if (Matches1("START"))
3029 COMPLETE_WITH_CONST("TRANSACTION");
3031 /* TABLE, but not TABLE embedded in other commands */
3032 else if (Matches1("TABLE"))
3033 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3036 else if (TailMatches1("TABLESAMPLE"))
3037 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
3038 else if (TailMatches2("TABLESAMPLE", MatchAny))
3039 COMPLETE_WITH_CONST("(");
3042 else if (Matches1("TRUNCATE"))
3043 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3046 else if (Matches1("UNLISTEN"))
3047 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 '*'");
3049 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
3050 /* If prev. word is UPDATE suggest a list of tables */
3051 else if (TailMatches1("UPDATE"))
3052 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3053 /* Complete UPDATE <table> with "SET" */
3054 else if (TailMatches2("UPDATE", MatchAny))
3055 COMPLETE_WITH_CONST("SET");
3056 /* Complete UPDATE <table> SET with list of attributes */
3057 else if (TailMatches3("UPDATE", MatchAny, "SET"))
3058 COMPLETE_WITH_ATTR(prev2_wd, "");
3059 /* UPDATE <table> SET <attr> = */
3060 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
3061 COMPLETE_WITH_CONST("=");
3064 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
3065 COMPLETE_WITH_CONST("FOR");
3066 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
3067 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3068 " UNION SELECT 'CURRENT_USER'"
3069 " UNION SELECT 'PUBLIC'"
3070 " UNION SELECT 'USER'");
3071 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
3072 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3073 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
3074 COMPLETE_WITH_CONST("SERVER");
3075 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
3076 COMPLETE_WITH_CONST("OPTIONS");
3079 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
3080 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
3082 else if (Matches1("VACUUM"))
3083 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3084 " UNION SELECT 'FULL'"
3085 " UNION SELECT 'FREEZE'"
3086 " UNION SELECT 'ANALYZE'"
3087 " UNION SELECT 'VERBOSE'");
3088 else if (Matches2("VACUUM", "FULL|FREEZE"))
3089 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3090 " UNION SELECT 'ANALYZE'"
3091 " UNION SELECT 'VERBOSE'");
3092 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
3093 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3094 " UNION SELECT 'VERBOSE'");
3095 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
3096 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3097 " UNION SELECT 'ANALYZE'");
3098 else if (Matches2("VACUUM", "VERBOSE"))
3099 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3100 " UNION SELECT 'ANALYZE'");
3101 else if (Matches2("VACUUM", "ANALYZE"))
3102 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3103 " UNION SELECT 'VERBOSE'");
3104 else if (HeadMatches1("VACUUM"))
3105 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3107 /* WITH [RECURSIVE] */
3110 * Only match when WITH is the first word, as WITH may appear in many
3113 else if (Matches1("WITH"))
3114 COMPLETE_WITH_CONST("RECURSIVE");
3117 /* Complete with list of tables */
3118 else if (Matches1("ANALYZE"))
3119 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
3122 /* Simple case of the word before the where being the table name */
3123 else if (TailMatches2(MatchAny, "WHERE"))
3124 COMPLETE_WITH_ATTR(prev2_wd, "");
3127 /* TODO: also include SRF ? */
3128 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
3129 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3132 else if (TailMatches1("JOIN"))
3133 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3135 /* Backslash commands */
3136 /* TODO: \dc \dd \dl */
3137 else if (TailMatchesCS1("\\?"))
3138 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
3139 else if (TailMatchesCS1("\\connect|\\c"))
3141 if (!recognized_connection_string(text))
3142 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3144 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
3146 if (!recognized_connection_string(prev_wd))
3147 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3149 else if (TailMatchesCS1("\\da*"))
3150 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
3151 else if (TailMatchesCS1("\\dA*"))
3152 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3153 else if (TailMatchesCS1("\\db*"))
3154 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3155 else if (TailMatchesCS1("\\dD*"))
3156 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3157 else if (TailMatchesCS1("\\des*"))
3158 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3159 else if (TailMatchesCS1("\\deu*"))
3160 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3161 else if (TailMatchesCS1("\\dew*"))
3162 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3163 else if (TailMatchesCS1("\\df*"))
3164 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3166 else if (TailMatchesCS1("\\dFd*"))
3167 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
3168 else if (TailMatchesCS1("\\dFp*"))
3169 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
3170 else if (TailMatchesCS1("\\dFt*"))
3171 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
3172 /* must be at end of \dF alternatives: */
3173 else if (TailMatchesCS1("\\dF*"))
3174 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
3176 else if (TailMatchesCS1("\\di*"))
3177 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3178 else if (TailMatchesCS1("\\dL*"))
3179 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3180 else if (TailMatchesCS1("\\dn*"))
3181 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3182 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
3183 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3184 else if (TailMatchesCS1("\\ds*"))
3185 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3186 else if (TailMatchesCS1("\\dt*"))
3187 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3188 else if (TailMatchesCS1("\\dT*"))
3189 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3190 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
3191 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3192 else if (TailMatchesCS1("\\dv*"))
3193 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3194 else if (TailMatchesCS1("\\dx*"))
3195 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
3196 else if (TailMatchesCS1("\\dm*"))
3197 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3198 else if (TailMatchesCS1("\\dE*"))
3199 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3200 else if (TailMatchesCS1("\\dy*"))
3201 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3203 /* must be at end of \d alternatives: */
3204 else if (TailMatchesCS1("\\d*"))
3205 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3207 else if (TailMatchesCS1("\\ef"))
3208 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3209 else if (TailMatchesCS1("\\ev"))
3210 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3212 else if (TailMatchesCS1("\\encoding"))
3213 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3214 else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
3215 COMPLETE_WITH_LIST(sql_commands);
3216 else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
3217 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3218 else if (TailMatchesCS1("\\password"))
3219 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3220 else if (TailMatchesCS1("\\pset"))
3222 static const char *const my_list[] =
3223 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3224 "footer", "format", "linestyle", "null", "numericlocale",
3225 "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3226 "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3227 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3229 COMPLETE_WITH_LIST_CS(my_list);
3231 else if (TailMatchesCS2("\\pset", MatchAny))
3233 if (TailMatchesCS1("format"))
3235 static const char *const my_list[] =
3236 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3237 "latex", "latex-longtable", "troff-ms", NULL};
3239 COMPLETE_WITH_LIST_CS(my_list);
3241 else if (TailMatchesCS1("linestyle"))
3242 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3243 else if (TailMatchesCS1("unicode_border_linestyle|"
3244 "unicode_column_linestyle|"
3245 "unicode_header_linestyle"))
3246 COMPLETE_WITH_LIST_CS2("single", "double");
3248 else if (TailMatchesCS1("\\unset"))
3250 matches = complete_from_variables(text, "", "", true);
3252 else if (TailMatchesCS1("\\set"))
3254 matches = complete_from_variables(text, "", "", false);
3256 else if (TailMatchesCS2("\\set", MatchAny))
3258 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3259 "SINGLELINE|SINGLESTEP"))
3260 COMPLETE_WITH_LIST_CS2("on", "off");
3261 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3262 COMPLETE_WITH_LIST_CS4("lower", "upper",
3263 "preserve-lower", "preserve-upper");
3264 else if (TailMatchesCS1("ECHO"))
3265 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3266 else if (TailMatchesCS1("ECHO_HIDDEN"))
3267 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3268 else if (TailMatchesCS1("HISTCONTROL"))
3269 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3270 "ignoreboth", "none");
3271 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3272 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3273 else if (TailMatchesCS1("SHOW_CONTEXT"))
3274 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3275 else if (TailMatchesCS1("VERBOSITY"))
3276 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3278 else if (TailMatchesCS1("\\sf*"))
3279 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3280 else if (TailMatchesCS1("\\sv*"))
3281 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3282 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3283 "\\ir|\\include_relative|\\o|\\out|"
3284 "\\s|\\w|\\write|\\lo_import"))
3286 completion_charp = "\\";
3287 matches = completion_matches(text, complete_from_files);
3291 * Finally, we look through the list of "things", such as TABLE, INDEX and
3292 * check if that was the previous word. If so, execute the query to get a
3299 for (i = 0; words_after_create[i].name; i++)
3301 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3303 if (words_after_create[i].query)
3304 COMPLETE_WITH_QUERY(words_after_create[i].query);
3305 else if (words_after_create[i].squery)
3306 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3314 * If we still don't have anything to match we have to fabricate some sort
3315 * of default list. If we were to just return NULL, readline automatically
3316 * attempts filename completion, and that's usually no good.
3318 if (matches == NULL)
3320 COMPLETE_WITH_CONST("");
3321 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3322 rl_completion_append_character = '\0';
3327 free(previous_words);
3330 /* Return our Grand List O' Matches */
3336 * GENERATOR FUNCTIONS
3338 * These functions do all the actual work of completing the input. They get
3339 * passed the text so far and the count how many times they have been called
3340 * so far with the same text.
3341 * If you read the above carefully, you'll see that these don't get called
3342 * directly but through the readline interface.
3343 * The return value is expected to be the full completion of the text, going
3344 * through a list each time, or NULL if there are no more matches. The string
3345 * will be free()'d by readline, so you must run it through strdup() or
3346 * something of that sort.
3350 * Common routine for create_command_generator and drop_command_generator.
3351 * Entries that have 'excluded' flags are not returned.
3354 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3356 static int list_index,
3360 /* If this is the first time for this completion, init some values */
3364 string_length = strlen(text);
3367 /* find something that matches */
3368 while ((name = words_after_create[list_index++].name))
3370 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3371 !(words_after_create[list_index - 1].flags & excluded))
3372 return pg_strdup_keyword_case(name, text);
3374 /* if nothing matches, return NULL */
3379 * This one gives you one from a list of things you can put after CREATE
3383 create_command_generator(const char *text, int state)
3385 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3389 * This function gives you a list of things you can put after a DROP command.
3392 drop_command_generator(const char *text, int state)
3394 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3397 /* The following two functions are wrappers for _complete_from_query */
3400 complete_from_query(const char *text, int state)
3402 return _complete_from_query(0, text, state);
3406 complete_from_schema_query(const char *text, int state)
3408 return _complete_from_query(1, text, state);
3413 * This creates a list of matching things, according to a query pointed to
3414 * by completion_charp.
3415 * The query can be one of two kinds:
3417 * 1. A simple query which must contain a %d and a %s, which will be replaced
3418 * by the string length of the text and the text itself. The query may also
3419 * have up to four more %s in it; the first two such will be replaced by the
3420 * value of completion_info_charp, the next two by the value of
3421 * completion_info_charp2.
3423 * 2. A schema query used for completion of both schema and relation names.
3424 * These are more complex and must contain in the following order:
3425 * %d %s %d %s %d %s %s %d %s
3426 * where %d is the string length of the text and %s the text itself.
3428 * It is assumed that strings should be escaped to become SQL literals
3429 * (that is, what is in the query is actually ... '%s' ...)
3431 * See top of file for examples of both kinds of query.
3434 _complete_from_query(int is_schema_query, const char *text, int state)
3436 static int list_index,
3438 static PGresult *result = NULL;
3441 * If this is the first time for this completion, we fetch a list of our
3442 * "things" from the backend.
3446 PQExpBufferData query_buffer;
3449 char *e_info_charp2;
3450 const char *pstr = text;
3451 int char_length = 0;
3454 byte_length = strlen(text);
3457 * Count length as number of characters (not bytes), for passing to
3463 pstr += PQmblen(pstr, pset.encoding);
3466 /* Free any prior result */
3470 /* Set up suitably-escaped copies of textual inputs */
3471 e_text = escape_string(text);
3473 if (completion_info_charp)
3474 e_info_charp = escape_string(completion_info_charp);
3476 e_info_charp = NULL;
3478 if (completion_info_charp2)
3479 e_info_charp2 = escape_string(completion_info_charp2);
3481 e_info_charp2 = NULL;
3483 initPQExpBuffer(&query_buffer);
3485 if (is_schema_query)
3487 /* completion_squery gives us the pieces to assemble */
3488 const char *qualresult = completion_squery->qualresult;
3490 if (qualresult == NULL)
3491 qualresult = completion_squery->result;
3493 /* Get unqualified names matching the input-so-far */
3494 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3495 completion_squery->result,
3496 completion_squery->catname);
3497 if (completion_squery->selcondition)
3498 appendPQExpBuffer(&query_buffer, "%s AND ",
3499 completion_squery->selcondition);
3500 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3501 completion_squery->result,
3502 char_length, e_text);
3503 appendPQExpBuffer(&query_buffer, " AND %s",
3504 completion_squery->viscondition);
3507 * When fetching relation names, suppress system catalogs unless
3508 * the input-so-far begins with "pg_". This is a compromise
3509 * between not offering system catalogs for completion at all, and
3510 * having them swamp the result when the input is just "p".
3512 if (strcmp(completion_squery->catname,
3513 "pg_catalog.pg_class c") == 0 &&
3514 strncmp(text, "pg_", 3) !=0)
3516 appendPQExpBufferStr(&query_buffer,
3517 " AND c.relnamespace <> (SELECT oid FROM"
3518 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3522 * Add in matching schema names, but only if there is more than
3523 * one potential match among schema names.
3525 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3526 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3527 "FROM pg_catalog.pg_namespace n "
3528 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3529 char_length, e_text);
3530 appendPQExpBuffer(&query_buffer,
3531 " AND (SELECT pg_catalog.count(*)"
3532 " FROM pg_catalog.pg_namespace"
3533 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3534 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3535 char_length, e_text);
3538 * Add in matching qualified names, but only if there is exactly
3539 * one schema matching the input-so-far.
3541 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3542 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3543 "FROM %s, pg_catalog.pg_namespace n "
3544 "WHERE %s = n.oid AND ",
3546 completion_squery->catname,
3547 completion_squery->namespace);
3548 if (completion_squery->selcondition)
3549 appendPQExpBuffer(&query_buffer, "%s AND ",
3550 completion_squery->selcondition);
3551 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3553 char_length, e_text);
3556 * This condition exploits the single-matching-schema rule to
3557 * speed up the query
3559 appendPQExpBuffer(&query_buffer,
3560 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3561 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3562 char_length, e_text);
3563 appendPQExpBuffer(&query_buffer,
3564 " AND (SELECT pg_catalog.count(*)"
3565 " FROM pg_catalog.pg_namespace"
3566 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3567 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3568 char_length, e_text);
3570 /* If an addon query was provided, use it */
3571 if (completion_charp)
3572 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3576 /* completion_charp is an sprintf-style format string */
3577 appendPQExpBuffer(&query_buffer, completion_charp,
3578 char_length, e_text,
3579 e_info_charp, e_info_charp,
3580 e_info_charp2, e_info_charp2);
3583 /* Limit the number of records in the result */
3584 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3585 completion_max_records);
3587 result = exec_query(query_buffer.data);
3589 termPQExpBuffer(&query_buffer);
3594 free(e_info_charp2);
3597 /* Find something that matches */
3598 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3602 while (list_index < PQntuples(result) &&
3603 (item = PQgetvalue(result, list_index++, 0)))
3604 if (pg_strncasecmp(text, item, byte_length) == 0)
3605 return pg_strdup(item);
3608 /* If nothing matches, free the db structure and return null */
3616 * This function returns in order one of a fixed, NULL pointer terminated list
3617 * of strings (if matching). This can be used if there are only a fixed number
3618 * SQL words that can appear at certain spot.
3621 complete_from_list(const char *text, int state)
3623 static int string_length,
3626 static bool casesensitive;
3629 /* need to have a list */
3630 Assert(completion_charpp != NULL);
3632 /* Initialization */
3636 string_length = strlen(text);
3637 casesensitive = completion_case_sensitive;
3641 while ((item = completion_charpp[list_index++]))
3643 /* First pass is case sensitive */
3644 if (casesensitive && strncmp(text, item, string_length) == 0)
3647 return pg_strdup(item);
3650 /* Second pass is case insensitive, don't bother counting matches */
3651 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3653 if (completion_case_sensitive)
3654 return pg_strdup(item);
3658 * If case insensitive matching was requested initially,
3659 * adjust the case according to setting.
3661 return pg_strdup_keyword_case(item, text);
3666 * No matches found. If we're not case insensitive already, lets switch to
3667 * being case insensitive and try again
3669 if (casesensitive && matches == 0)
3671 casesensitive = false;
3674 return complete_from_list(text, state);
3677 /* If no more matches, return null. */
3683 * This function returns one fixed string the first time even if it doesn't
3684 * match what's there, and nothing the second time. This should be used if
3685 * there is only one possibility that can appear at a certain spot, so
3686 * misspellings will be overwritten. The string to be passed must be in
3690 complete_from_const(const char *text, int state)
3692 Assert(completion_charp != NULL);
3695 if (completion_case_sensitive)
3696 return pg_strdup(completion_charp);
3700 * If case insensitive matching was requested initially, adjust
3701 * the case according to setting.
3703 return pg_strdup_keyword_case(completion_charp, text);
3711 * This function appends the variable name with prefix and suffix to
3712 * the variable names array.
3715 append_variable_names(char ***varnames, int *nvars,
3716 int *maxvars, const char *varname,
3717 const char *prefix, const char *suffix)
3719 if (*nvars >= *maxvars)
3722 *varnames = (char **) pg_realloc(*varnames,
3723 ((*maxvars) + 1) * sizeof(char *));
3726 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3731 * This function supports completion with the name of a psql variable.
3732 * The variable names can be prefixed and suffixed with additional text
3733 * to support quoting usages. If need_value is true, only the variables
3734 * that have the set values are picked up.
3737 complete_from_variables(const char *text, const char *prefix, const char *suffix,
3745 struct _variable *ptr;
3747 static const char *const known_varnames[] = {
3748 "AUTOCOMMIT", "COMP_KEYWORD_CASE", "DBNAME", "ECHO", "ECHO_HIDDEN",
3749 "ENCODING", "FETCH_COUNT", "HISTCONTROL", "HISTFILE", "HISTSIZE",
3750 "HOST", "IGNOREEOF", "LASTOID", "ON_ERROR_ROLLBACK", "ON_ERROR_STOP",
3751 "PORT", "PROMPT1", "PROMPT2", "PROMPT3", "QUIET",
3752 "SHOW_CONTEXT", "SINGLELINE", "SINGLESTEP",
3753 "USER", "VERBOSITY", NULL
3756 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
3760 for (i = 0; known_varnames[i] && nvars < maxvars; i++)
3761 append_variable_names(&varnames, &nvars, &maxvars,
3762 known_varnames[i], prefix, suffix);
3765 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3767 if (need_value && !(ptr->value))
3769 for (i = 0; known_varnames[i]; i++) /* remove duplicate entry */
3771 if (strcmp(ptr->name, known_varnames[i]) == 0)
3774 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3778 varnames[nvars] = NULL;
3779 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
3781 for (i = 0; i < nvars; i++)
3790 * This function wraps rl_filename_completion_function() to strip quotes from
3791 * the input before searching for matches and to quote any matches for which
3792 * the consuming command will require it.
3795 complete_from_files(const char *text, int state)
3797 static const char *unquoted_text;
3798 char *unquoted_match;
3803 /* Initialization: stash the unquoted input. */
3804 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
3805 false, true, pset.encoding);
3806 /* expect a NULL return for the empty string only */
3809 Assert(*text == '\0');
3810 unquoted_text = text;
3814 unquoted_match = filename_completion_function(unquoted_text, state);
3818 * Caller sets completion_charp to a zero- or one-character string
3819 * containing the escape character. This is necessary since \copy has
3820 * no escape character, but every other backslash command recognizes
3821 * "\" as an escape character. Since we have only two callers, don't
3822 * bother providing a macro to simplify this.
3824 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
3825 '\'', *completion_charp, pset.encoding);
3827 free(unquoted_match);
3829 ret = unquoted_match;
3836 /* HELPER FUNCTIONS */
3840 * Make a pg_strdup copy of s and convert the case according to
3841 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
3844 pg_strdup_keyword_case(const char *s, const char *ref)
3848 unsigned char first = ref[0];
3852 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
3853 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
3854 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
3855 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
3857 for (p = ret; *p; p++)
3858 *p = pg_tolower((unsigned char) *p);
3862 for (p = ret; *p; p++)
3863 *p = pg_toupper((unsigned char) *p);
3871 * escape_string - Escape argument for use as string literal.
3873 * The returned value has to be freed.
3876 escape_string(const char *text)
3881 text_length = strlen(text);
3883 result = pg_malloc(text_length * 2 + 1);
3884 PQescapeStringConn(pset.db, result, text, text_length, NULL);
3891 * Execute a query and report any errors. This should be the preferred way of
3892 * talking to the database in this file.
3895 exec_query(const char *query)
3899 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
3902 result = PQexec(pset.db, query);
3904 if (PQresultStatus(result) != PGRES_TUPLES_OK)
3907 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
3908 PQerrorMessage(pset.db), query);
3919 * Parse all the word(s) before point.
3921 * Returns a malloc'd array of character pointers that point into the malloc'd
3922 * data array returned to *buffer; caller must free() both of these when done.
3923 * *nwords receives the number of words found, ie, the valid length of the
3926 * Words are returned right to left, that is, previous_words[0] gets the last
3927 * word before point, previous_words[1] the next-to-last, etc.
3930 get_previous_words(int point, char **buffer, int *nwords)
3932 char **previous_words;
3935 int words_found = 0;
3939 * If we have anything in tab_completion_query_buf, paste it together with
3940 * rl_line_buffer to construct the full query. Otherwise we can just use
3941 * rl_line_buffer as the input string.
3943 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
3945 i = tab_completion_query_buf->len;
3946 buf = pg_malloc(point + i + 2);
3947 memcpy(buf, tab_completion_query_buf->data, i);
3949 memcpy(buf + i, rl_line_buffer, point);
3952 /* Readjust point to reference appropriate offset in buf */
3956 buf = rl_line_buffer;
3959 * Allocate an array of string pointers and a buffer to hold the strings
3960 * themselves. The worst case is that the line contains only
3961 * non-whitespace WORD_BREAKS characters, making each one a separate word.
3962 * This is usually much more space than we need, but it's cheaper than
3963 * doing a separate malloc() for each word.
3965 previous_words = (char **) pg_malloc(point * sizeof(char *));
3966 *buffer = outptr = (char *) pg_malloc(point * 2);
3969 * First we look for a non-word char before the current point. (This is
3970 * probably useless, if readline is on the same page as we are about what
3971 * is a word, but if so it's cheap.)
3973 for (i = point - 1; i >= 0; i--)
3975 if (strchr(WORD_BREAKS, buf[i]))
3981 * Now parse words, working backwards, until we hit start of line. The
3982 * backwards scan has some interesting but intentional properties
3983 * concerning parenthesis handling.
3989 bool inquotes = false;
3990 int parentheses = 0;
3992 /* now find the first non-space which then constitutes the end */
3994 for (i = point; i >= 0; i--)
3996 if (!isspace((unsigned char) buf[i]))
4002 /* if no end found, we're done */
4007 * Otherwise we now look for the start. The start is either the last
4008 * character before any word-break character going backwards from the
4009 * end, or it's simply character 0. We also handle open quotes and
4012 for (start = end; start > 0; start--)
4014 if (buf[start] == '"')
4015 inquotes = !inquotes;
4018 if (buf[start] == ')')
4020 else if (buf[start] == '(')
4022 if (--parentheses <= 0)
4025 else if (parentheses == 0 &&
4026 strchr(WORD_BREAKS, buf[start - 1]))
4031 /* Return the word located at start to end inclusive */
4032 previous_words[words_found++] = outptr;
4033 i = end - start + 1;
4034 memcpy(outptr, &buf[start], i);
4038 /* Continue searching */
4042 /* Release parsing input workspace, if we made one above */
4043 if (buf != rl_line_buffer)
4046 *nwords = words_found;
4047 return previous_words;
4051 * Look up the type for the GUC variable with the passed name.
4053 * Returns NULL if the variable is unknown. Otherwise the returned string,
4054 * containing the type, has to be freed.
4057 get_guctype(const char *varname)
4059 PQExpBufferData query_buffer;
4062 char *guctype = NULL;
4064 e_varname = escape_string(varname);
4066 initPQExpBuffer(&query_buffer);
4067 appendPQExpBuffer(&query_buffer,
4068 "SELECT vartype FROM pg_catalog.pg_settings "
4069 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
4072 result = exec_query(query_buffer.data);
4073 termPQExpBuffer(&query_buffer);
4076 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
4077 guctype = pg_strdup(PQgetvalue(result, 0, 0));
4087 * Surround a string with single quotes. This works for both SQL and
4088 * psql internal. Currently disabled because it is reported not to
4089 * cooperate with certain versions of readline.
4092 quote_file_name(char *text, int match_type, char *quote_pointer)
4097 (void) quote_pointer; /* not used */
4099 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
4100 s = pg_malloc(length);
4102 strcpy(s + 1, text);
4103 if (match_type == SINGLE_MATCH)
4104 s[length - 2] = '\'';
4105 s[length - 1] = '\0';
4110 dequote_file_name(char *text, char quote_char)
4116 return pg_strdup(text);
4118 length = strlen(text);
4119 s = pg_malloc(length - 2 + 1);
4120 strlcpy(s, text +1, length - 2 + 1);
4124 #endif /* NOT_USED */
4126 #endif /* USE_READLINE */