2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2017, PostgreSQL Global Development Group
6 * src/bin/psql/tab-complete.c
9 /*----------------------------------------------------------------------
10 * This file implements a somewhat more sophisticated readline "TAB
11 * completion" in psql. It is not intended to be AI, to replace
12 * learning SQL, or to relieve you from thinking about what you're
13 * doing. Also it does not always give you all the syntactically legal
14 * completions, only those that are the most common or the ones that
15 * the programmer felt most like implementing.
17 * CAVEAT: Tab completion causes queries to be sent to the backend.
18 * The number of tuples returned gets limited, in most default
19 * installations to 1000, but if you still don't like this prospect,
20 * you can turn off tab completion in your ~/.inputrc (or else
21 * ${INPUTRC}) file so:
24 * set disable-completion on
27 * See `man 3 readline' or `info readline' for the full details.
30 * - Quotes, parentheses, and other funny characters are not handled
31 * all that gracefully.
32 *----------------------------------------------------------------------
35 #include "postgres_fe.h"
36 #include "tab-complete.h"
39 /* If we don't have this, we might as well forget about the whole thing: */
44 #include "catalog/pg_class.h"
47 #include "pqexpbuffer.h"
50 #include "stringutils.h"
52 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
53 #define filename_completion_function rl_filename_completion_function
55 /* missing in some header files */
56 extern char *filename_completion_function();
59 #ifdef HAVE_RL_COMPLETION_MATCHES
60 #define completion_matches rl_completion_matches
63 /* word break characters */
64 #define WORD_BREAKS "\t\n@$><=;|&{() "
67 * Since readline doesn't let us pass any state through to the tab completion
68 * callback, we have to use this global variable to let get_previous_words()
69 * get at the previous lines of the current command. Ick.
71 PQExpBuffer tab_completion_query_buf = NULL;
74 * This struct is used to define "schema queries", which are custom-built
75 * to obtain possibly-schema-qualified names of database objects. There is
76 * enough similarity in the structure that we don't want to repeat it each
77 * time. So we put the components of each query into this struct and
78 * assemble them with the common boilerplate in _complete_from_query().
80 typedef struct SchemaQuery
83 * Name of catalog or catalogs to be queried, with alias, eg.
84 * "pg_catalog.pg_class c". Note that "pg_namespace n" will be added.
89 * Selection condition --- only rows meeting this condition are candidates
90 * to display. If catname mentions multiple tables, include the necessary
91 * join condition here. For example, this might look like "c.relkind = "
92 * CppAsString2(RELKIND_RELATION). Write NULL (not an empty string) if
95 const char *selcondition;
98 * Visibility condition --- which rows are visible without schema
99 * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
101 const char *viscondition;
104 * Namespace --- name of field to join to pg_namespace.oid. For example,
107 const char *namespace;
110 * Result --- the appropriately-quoted name to return, in the case of an
111 * unqualified name. For example, "pg_catalog.quote_ident(c.relname)".
116 * In some cases a different result must be used for qualified names.
117 * Enter that here, or write NULL if result can be used.
119 const char *qualresult;
123 /* Store maximum number of records we want from database queries
124 * (implemented via SELECT ... LIMIT xx).
126 static int completion_max_records;
129 * Communication variables set by COMPLETE_WITH_FOO macros and then used by
130 * the completion callback functions. Ugly but there is no better way.
132 static const char *completion_charp; /* to pass a string */
133 static const char *const *completion_charpp; /* to pass a list of strings */
134 static const char *completion_info_charp; /* to pass a second string */
135 static const char *completion_info_charp2; /* to pass a third string */
136 static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
137 static bool completion_case_sensitive; /* completion is case sensitive */
140 * A few macros to ease typing. You can use these to complete the given
142 * 1) The results from a query you pass it. (Perhaps one of those below?)
143 * 2) The results from a schema query you pass it.
144 * 3) The items from a null-pointer-terminated list (with or without
145 * case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
146 * 4) A string constant.
147 * 5) The list of attributes of the given table (possibly schema-qualified).
148 * 6/ The list of arguments to the given function (possibly schema-qualified).
150 #define COMPLETE_WITH_QUERY(query) \
152 completion_charp = query; \
153 matches = completion_matches(text, complete_from_query); \
156 #define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
158 completion_squery = &(query); \
159 completion_charp = addon; \
160 matches = completion_matches(text, complete_from_schema_query); \
163 #define COMPLETE_WITH_LIST_CS(list) \
165 completion_charpp = list; \
166 completion_case_sensitive = true; \
167 matches = completion_matches(text, complete_from_list); \
170 #define COMPLETE_WITH_LIST(list) \
172 completion_charpp = list; \
173 completion_case_sensitive = false; \
174 matches = completion_matches(text, complete_from_list); \
177 #define COMPLETE_WITH_CONST(string) \
179 completion_charp = string; \
180 completion_case_sensitive = false; \
181 matches = completion_matches(text, complete_from_const); \
184 #define COMPLETE_WITH_ATTR(relation, addon) \
186 char *_completion_schema; \
187 char *_completion_table; \
189 _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
190 false, false, pset.encoding); \
191 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
192 false, false, pset.encoding); \
193 _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
194 false, false, pset.encoding); \
195 if (_completion_table == NULL) \
197 completion_charp = Query_for_list_of_attributes addon; \
198 completion_info_charp = relation; \
202 completion_charp = Query_for_list_of_attributes_with_schema addon; \
203 completion_info_charp = _completion_table; \
204 completion_info_charp2 = _completion_schema; \
206 matches = completion_matches(text, complete_from_query); \
209 #define COMPLETE_WITH_ENUM_VALUE(type) \
211 char *_completion_schema; \
212 char *_completion_type; \
214 _completion_schema = strtokx(type, " \t\n\r", ".", "\"", 0, \
215 false, false, pset.encoding); \
216 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
217 false, false, pset.encoding); \
218 _completion_type = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
219 false, false, pset.encoding); \
220 if (_completion_type == NULL)\
222 completion_charp = Query_for_list_of_enum_values; \
223 completion_info_charp = type; \
227 completion_charp = Query_for_list_of_enum_values_with_schema; \
228 completion_info_charp = _completion_type; \
229 completion_info_charp2 = _completion_schema; \
231 matches = completion_matches(text, complete_from_query); \
234 #define COMPLETE_WITH_FUNCTION_ARG(function) \
236 char *_completion_schema; \
237 char *_completion_function; \
239 _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
240 false, false, pset.encoding); \
241 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
242 false, false, pset.encoding); \
243 _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
244 false, false, pset.encoding); \
245 if (_completion_function == NULL) \
247 completion_charp = Query_for_list_of_arguments; \
248 completion_info_charp = function; \
252 completion_charp = Query_for_list_of_arguments_with_schema; \
253 completion_info_charp = _completion_function; \
254 completion_info_charp2 = _completion_schema; \
256 matches = completion_matches(text, complete_from_query); \
260 * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
261 * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
263 #define COMPLETE_WITH_LIST2(s1, s2) \
265 static const char *const list[] = { s1, s2, NULL }; \
266 COMPLETE_WITH_LIST(list); \
269 #define COMPLETE_WITH_LIST3(s1, s2, s3) \
271 static const char *const list[] = { s1, s2, s3, NULL }; \
272 COMPLETE_WITH_LIST(list); \
275 #define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
277 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
278 COMPLETE_WITH_LIST(list); \
281 #define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
283 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
284 COMPLETE_WITH_LIST(list); \
287 #define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \
289 static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \
290 COMPLETE_WITH_LIST(list); \
293 #define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \
295 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \
296 COMPLETE_WITH_LIST(list); \
299 #define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \
301 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \
302 COMPLETE_WITH_LIST(list); \
305 #define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
307 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
308 COMPLETE_WITH_LIST(list); \
311 #define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
313 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
314 COMPLETE_WITH_LIST(list); \
318 * Likewise for COMPLETE_WITH_LIST_CS.
320 #define COMPLETE_WITH_LIST_CS2(s1, s2) \
322 static const char *const list[] = { s1, s2, NULL }; \
323 COMPLETE_WITH_LIST_CS(list); \
326 #define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
328 static const char *const list[] = { s1, s2, s3, NULL }; \
329 COMPLETE_WITH_LIST_CS(list); \
332 #define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
334 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
335 COMPLETE_WITH_LIST_CS(list); \
338 #define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
340 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
341 COMPLETE_WITH_LIST_CS(list); \
345 * Assembly instructions for schema queries
348 static const SchemaQuery Query_for_list_of_aggregates = {
350 "pg_catalog.pg_proc p",
354 "pg_catalog.pg_function_is_visible(p.oid)",
358 "pg_catalog.quote_ident(p.proname)",
363 static const SchemaQuery Query_for_list_of_datatypes = {
365 "pg_catalog.pg_type t",
366 /* selcondition --- ignore table rowtypes and array types */
368 " OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
369 " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
370 "AND t.typname !~ '^_'",
372 "pg_catalog.pg_type_is_visible(t.oid)",
376 "pg_catalog.format_type(t.oid, NULL)",
378 "pg_catalog.quote_ident(t.typname)"
381 static const SchemaQuery Query_for_list_of_domains = {
383 "pg_catalog.pg_type t",
387 "pg_catalog.pg_type_is_visible(t.oid)",
391 "pg_catalog.quote_ident(t.typname)",
396 static const SchemaQuery Query_for_list_of_functions = {
398 "pg_catalog.pg_proc p",
402 "pg_catalog.pg_function_is_visible(p.oid)",
406 "pg_catalog.quote_ident(p.proname)",
411 static const SchemaQuery Query_for_list_of_indexes = {
413 "pg_catalog.pg_class c",
415 "c.relkind IN (" CppAsString2(RELKIND_INDEX) ")",
417 "pg_catalog.pg_table_is_visible(c.oid)",
421 "pg_catalog.quote_ident(c.relname)",
426 static const SchemaQuery Query_for_list_of_sequences = {
428 "pg_catalog.pg_class c",
430 "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
432 "pg_catalog.pg_table_is_visible(c.oid)",
436 "pg_catalog.quote_ident(c.relname)",
441 static const SchemaQuery Query_for_list_of_foreign_tables = {
443 "pg_catalog.pg_class c",
445 "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
447 "pg_catalog.pg_table_is_visible(c.oid)",
451 "pg_catalog.quote_ident(c.relname)",
456 static const SchemaQuery Query_for_list_of_tables = {
458 "pg_catalog.pg_class c",
460 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
461 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
463 "pg_catalog.pg_table_is_visible(c.oid)",
467 "pg_catalog.quote_ident(c.relname)",
472 static const SchemaQuery Query_for_list_of_partitioned_tables = {
474 "pg_catalog.pg_class c",
476 "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
478 "pg_catalog.pg_table_is_visible(c.oid)",
482 "pg_catalog.quote_ident(c.relname)",
487 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
489 "pg_catalog.pg_constraint c",
493 "true", /* there is no pg_constraint_is_visible */
497 "pg_catalog.quote_ident(c.conname)",
502 /* Relations supporting INSERT, UPDATE or DELETE */
503 static const SchemaQuery Query_for_list_of_updatables = {
505 "pg_catalog.pg_class c",
507 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
508 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
509 CppAsString2(RELKIND_VIEW) ", "
510 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
512 "pg_catalog.pg_table_is_visible(c.oid)",
516 "pg_catalog.quote_ident(c.relname)",
521 static const SchemaQuery Query_for_list_of_relations = {
523 "pg_catalog.pg_class c",
527 "pg_catalog.pg_table_is_visible(c.oid)",
531 "pg_catalog.quote_ident(c.relname)",
536 static const SchemaQuery Query_for_list_of_tsvmf = {
538 "pg_catalog.pg_class c",
540 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
541 CppAsString2(RELKIND_SEQUENCE) ", "
542 CppAsString2(RELKIND_VIEW) ", "
543 CppAsString2(RELKIND_MATVIEW) ", "
544 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
545 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
547 "pg_catalog.pg_table_is_visible(c.oid)",
551 "pg_catalog.quote_ident(c.relname)",
556 static const SchemaQuery Query_for_list_of_tmf = {
558 "pg_catalog.pg_class c",
560 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
561 CppAsString2(RELKIND_MATVIEW) ", "
562 CppAsString2(RELKIND_FOREIGN_TABLE) ")",
564 "pg_catalog.pg_table_is_visible(c.oid)",
568 "pg_catalog.quote_ident(c.relname)",
573 static const SchemaQuery Query_for_list_of_tm = {
575 "pg_catalog.pg_class c",
577 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
578 CppAsString2(RELKIND_MATVIEW) ")",
580 "pg_catalog.pg_table_is_visible(c.oid)",
584 "pg_catalog.quote_ident(c.relname)",
589 static const SchemaQuery Query_for_list_of_views = {
591 "pg_catalog.pg_class c",
593 "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
595 "pg_catalog.pg_table_is_visible(c.oid)",
599 "pg_catalog.quote_ident(c.relname)",
604 static const SchemaQuery Query_for_list_of_matviews = {
606 "pg_catalog.pg_class c",
608 "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
610 "pg_catalog.pg_table_is_visible(c.oid)",
614 "pg_catalog.quote_ident(c.relname)",
619 static const SchemaQuery Query_for_list_of_statistics = {
621 "pg_catalog.pg_statistic_ext s",
625 "pg_catalog.pg_statistics_obj_is_visible(s.oid)",
629 "pg_catalog.quote_ident(s.stxname)",
636 * Queries to get lists of names of various kinds of things, possibly
637 * restricted to names matching a partially entered name. In these queries,
638 * the first %s will be replaced by the text entered so far (suitably escaped
639 * to become a SQL literal string). %d will be replaced by the length of the
640 * string (in unescaped form). A second and third %s, if present, will be
641 * replaced by a suitably-escaped version of the string provided in
642 * completion_info_charp. A fourth and fifth %s are similarly replaced by
643 * completion_info_charp2.
645 * Beware that the allowed sequences of %s and %d are determined by
646 * _complete_from_query().
649 #define Query_for_list_of_attributes \
650 "SELECT pg_catalog.quote_ident(attname) "\
651 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
652 " WHERE c.oid = a.attrelid "\
653 " AND a.attnum > 0 "\
654 " AND NOT a.attisdropped "\
655 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
656 " AND (pg_catalog.quote_ident(relname)='%s' "\
657 " OR '\"' || relname || '\"'='%s') "\
658 " AND pg_catalog.pg_table_is_visible(c.oid)"
660 #define Query_for_list_of_attributes_with_schema \
661 "SELECT pg_catalog.quote_ident(attname) "\
662 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
663 " WHERE c.oid = a.attrelid "\
664 " AND n.oid = c.relnamespace "\
665 " AND a.attnum > 0 "\
666 " AND NOT a.attisdropped "\
667 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
668 " AND (pg_catalog.quote_ident(relname)='%s' "\
669 " OR '\"' || relname || '\"' ='%s') "\
670 " AND (pg_catalog.quote_ident(nspname)='%s' "\
671 " OR '\"' || nspname || '\"' ='%s') "
673 #define Query_for_list_of_enum_values \
674 "SELECT pg_catalog.quote_literal(enumlabel) "\
675 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t "\
676 " WHERE t.oid = e.enumtypid "\
677 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
678 " AND (pg_catalog.quote_ident(typname)='%s' "\
679 " OR '\"' || typname || '\"'='%s') "\
680 " AND pg_catalog.pg_type_is_visible(t.oid)"
682 #define Query_for_list_of_enum_values_with_schema \
683 "SELECT pg_catalog.quote_literal(enumlabel) "\
684 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
685 " WHERE t.oid = e.enumtypid "\
686 " AND n.oid = t.typnamespace "\
687 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
688 " AND (pg_catalog.quote_ident(typname)='%s' "\
689 " OR '\"' || typname || '\"'='%s') "\
690 " AND (pg_catalog.quote_ident(nspname)='%s' "\
691 " OR '\"' || nspname || '\"' ='%s') "
693 #define Query_for_list_of_template_databases \
694 "SELECT pg_catalog.quote_ident(d.datname) "\
695 " FROM pg_catalog.pg_database d "\
696 " WHERE substring(pg_catalog.quote_ident(d.datname),1,%d)='%s' "\
697 " AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
699 #define Query_for_list_of_databases \
700 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
701 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
703 #define Query_for_list_of_tablespaces \
704 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
705 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
707 #define Query_for_list_of_encodings \
708 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
709 " FROM pg_catalog.pg_conversion "\
710 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
712 #define Query_for_list_of_languages \
713 "SELECT pg_catalog.quote_ident(lanname) "\
714 " FROM pg_catalog.pg_language "\
715 " WHERE lanname != 'internal' "\
716 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
718 #define Query_for_list_of_schemas \
719 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
720 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
722 #define Query_for_list_of_alter_system_set_vars \
724 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
725 " WHERE context != 'internal' "\
726 " UNION ALL SELECT 'all') ss "\
727 " WHERE substring(name,1,%d)='%s'"
729 #define Query_for_list_of_set_vars \
731 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
732 " WHERE context IN ('user', 'superuser') "\
733 " UNION ALL SELECT 'constraints' "\
734 " UNION ALL SELECT 'transaction' "\
735 " UNION ALL SELECT 'session' "\
736 " UNION ALL SELECT 'role' "\
737 " UNION ALL SELECT 'tablespace' "\
738 " UNION ALL SELECT 'all') ss "\
739 " WHERE substring(name,1,%d)='%s'"
741 #define Query_for_list_of_show_vars \
743 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
744 " UNION ALL SELECT 'session authorization' "\
745 " UNION ALL SELECT 'all') ss "\
746 " WHERE substring(name,1,%d)='%s'"
748 #define Query_for_list_of_roles \
749 " SELECT pg_catalog.quote_ident(rolname) "\
750 " FROM pg_catalog.pg_roles "\
751 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
753 #define Query_for_list_of_grant_roles \
754 " SELECT pg_catalog.quote_ident(rolname) "\
755 " FROM pg_catalog.pg_roles "\
756 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
757 " UNION ALL SELECT 'PUBLIC'"\
758 " UNION ALL SELECT 'CURRENT_USER'"\
759 " UNION ALL SELECT 'SESSION_USER'"
761 /* the silly-looking length condition is just to eat up the current word */
762 #define Query_for_table_owning_index \
763 "SELECT pg_catalog.quote_ident(c1.relname) "\
764 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
765 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
766 " and (%d = pg_catalog.length('%s'))"\
767 " and pg_catalog.quote_ident(c2.relname)='%s'"\
768 " and pg_catalog.pg_table_is_visible(c2.oid)"
770 /* the silly-looking length condition is just to eat up the current word */
771 #define Query_for_index_of_table \
772 "SELECT pg_catalog.quote_ident(c2.relname) "\
773 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
774 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
775 " and (%d = pg_catalog.length('%s'))"\
776 " and pg_catalog.quote_ident(c1.relname)='%s'"\
777 " and pg_catalog.pg_table_is_visible(c2.oid)"
779 /* the silly-looking length condition is just to eat up the current word */
780 #define Query_for_constraint_of_table \
781 "SELECT pg_catalog.quote_ident(conname) "\
782 " FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
783 " WHERE c1.oid=conrelid 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)"
787 #define Query_for_all_table_constraints \
788 "SELECT pg_catalog.quote_ident(conname) "\
789 " FROM pg_catalog.pg_constraint c "\
790 " WHERE c.conrelid <> 0 "
792 /* the silly-looking length condition is just to eat up the current word */
793 #define Query_for_constraint_of_type \
794 "SELECT pg_catalog.quote_ident(conname) "\
795 " FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
796 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
797 " and pg_catalog.quote_ident(t.typname)='%s'"\
798 " and pg_catalog.pg_type_is_visible(t.oid)"
800 /* the silly-looking length condition is just to eat up the current word */
801 #define Query_for_list_of_tables_for_constraint \
802 "SELECT pg_catalog.quote_ident(relname) "\
803 " FROM pg_catalog.pg_class"\
804 " WHERE (%d = pg_catalog.length('%s'))"\
806 " (SELECT conrelid FROM pg_catalog.pg_constraint "\
807 " WHERE pg_catalog.quote_ident(conname)='%s')"
809 /* the silly-looking length condition is just to eat up the current word */
810 #define Query_for_rule_of_table \
811 "SELECT pg_catalog.quote_ident(rulename) "\
812 " FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
813 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
814 " and pg_catalog.quote_ident(c1.relname)='%s'"\
815 " and pg_catalog.pg_table_is_visible(c1.oid)"
817 /* the silly-looking length condition is just to eat up the current word */
818 #define Query_for_list_of_tables_for_rule \
819 "SELECT pg_catalog.quote_ident(relname) "\
820 " FROM pg_catalog.pg_class"\
821 " WHERE (%d = pg_catalog.length('%s'))"\
823 " (SELECT ev_class FROM pg_catalog.pg_rewrite "\
824 " WHERE pg_catalog.quote_ident(rulename)='%s')"
826 /* the silly-looking length condition is just to eat up the current word */
827 #define Query_for_trigger_of_table \
828 "SELECT pg_catalog.quote_ident(tgname) "\
829 " FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
830 " WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
831 " and pg_catalog.quote_ident(c1.relname)='%s'"\
832 " and pg_catalog.pg_table_is_visible(c1.oid)"\
833 " and not tgisinternal"
835 /* the silly-looking length condition is just to eat up the current word */
836 #define Query_for_list_of_tables_for_trigger \
837 "SELECT pg_catalog.quote_ident(relname) "\
838 " FROM pg_catalog.pg_class"\
839 " WHERE (%d = pg_catalog.length('%s'))"\
841 " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
842 " WHERE pg_catalog.quote_ident(tgname)='%s')"
844 #define Query_for_list_of_ts_configurations \
845 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
846 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
848 #define Query_for_list_of_ts_dictionaries \
849 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
850 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
852 #define Query_for_list_of_ts_parsers \
853 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
854 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
856 #define Query_for_list_of_ts_templates \
857 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
858 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
860 #define Query_for_list_of_fdws \
861 " SELECT pg_catalog.quote_ident(fdwname) "\
862 " FROM pg_catalog.pg_foreign_data_wrapper "\
863 " WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
865 #define Query_for_list_of_servers \
866 " SELECT pg_catalog.quote_ident(srvname) "\
867 " FROM pg_catalog.pg_foreign_server "\
868 " WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
870 #define Query_for_list_of_user_mappings \
871 " SELECT pg_catalog.quote_ident(usename) "\
872 " FROM pg_catalog.pg_user_mappings "\
873 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
875 #define Query_for_list_of_access_methods \
876 " SELECT pg_catalog.quote_ident(amname) "\
877 " FROM pg_catalog.pg_am "\
878 " WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
880 #define Query_for_list_of_publications \
881 " SELECT pg_catalog.quote_ident(pubname) "\
882 " FROM pg_catalog.pg_publication "\
883 " WHERE substring(pg_catalog.quote_ident(pubname),1,%d)='%s'"
885 #define Query_for_list_of_subscriptions \
886 " SELECT pg_catalog.quote_ident(s.subname) "\
887 " FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "\
888 " WHERE substring(pg_catalog.quote_ident(s.subname),1,%d)='%s' "\
889 " AND d.datname = pg_catalog.current_database() "\
890 " AND s.subdbid = d.oid"
892 /* the silly-looking length condition is just to eat up the current word */
893 #define Query_for_list_of_arguments \
894 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
895 " FROM pg_catalog.pg_proc "\
896 " WHERE (%d = pg_catalog.length('%s'))"\
897 " AND (pg_catalog.quote_ident(proname)='%s'"\
898 " OR '\"' || proname || '\"'='%s') "\
899 " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
901 /* the silly-looking length condition is just to eat up the current word */
902 #define Query_for_list_of_arguments_with_schema \
903 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
904 " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
905 " WHERE (%d = pg_catalog.length('%s'))"\
906 " AND n.oid = p.pronamespace "\
907 " AND (pg_catalog.quote_ident(proname)='%s' "\
908 " OR '\"' || proname || '\"' ='%s') "\
909 " AND (pg_catalog.quote_ident(nspname)='%s' "\
910 " OR '\"' || nspname || '\"' ='%s') "
912 #define Query_for_list_of_extensions \
913 " SELECT pg_catalog.quote_ident(extname) "\
914 " FROM pg_catalog.pg_extension "\
915 " WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
917 #define Query_for_list_of_available_extensions \
918 " SELECT pg_catalog.quote_ident(name) "\
919 " FROM pg_catalog.pg_available_extensions "\
920 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
922 /* the silly-looking length condition is just to eat up the current word */
923 #define Query_for_list_of_available_extension_versions \
924 " SELECT pg_catalog.quote_ident(version) "\
925 " FROM pg_catalog.pg_available_extension_versions "\
926 " WHERE (%d = pg_catalog.length('%s'))"\
927 " AND pg_catalog.quote_ident(name)='%s'"
929 /* the silly-looking length condition is just to eat up the current word */
930 #define Query_for_list_of_available_extension_versions_with_TO \
931 " SELECT 'TO ' || pg_catalog.quote_ident(version) "\
932 " FROM pg_catalog.pg_available_extension_versions "\
933 " WHERE (%d = pg_catalog.length('%s'))"\
934 " AND pg_catalog.quote_ident(name)='%s'"
936 #define Query_for_list_of_prepared_statements \
937 " SELECT pg_catalog.quote_ident(name) "\
938 " FROM pg_catalog.pg_prepared_statements "\
939 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
941 #define Query_for_list_of_event_triggers \
942 " SELECT pg_catalog.quote_ident(evtname) "\
943 " FROM pg_catalog.pg_event_trigger "\
944 " WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
946 #define Query_for_list_of_tablesample_methods \
947 " SELECT pg_catalog.quote_ident(proname) "\
948 " FROM pg_catalog.pg_proc "\
949 " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
950 " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
951 " substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
953 #define Query_for_list_of_policies \
954 " SELECT pg_catalog.quote_ident(polname) "\
955 " FROM pg_catalog.pg_policy "\
956 " WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
958 #define Query_for_list_of_tables_for_policy \
959 "SELECT pg_catalog.quote_ident(relname) "\
960 " FROM pg_catalog.pg_class"\
961 " WHERE (%d = pg_catalog.length('%s'))"\
963 " (SELECT polrelid FROM pg_catalog.pg_policy "\
964 " WHERE pg_catalog.quote_ident(polname)='%s')"
966 #define Query_for_enum \
967 " SELECT name FROM ( "\
968 " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
969 " FROM pg_catalog.pg_settings "\
970 " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
972 " SELECT 'DEFAULT' ) ss "\
973 " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
975 /* the silly-looking length condition is just to eat up the current word */
976 #define Query_for_partition_of_table \
977 "SELECT pg_catalog.quote_ident(c2.relname) "\
978 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i"\
979 " WHERE c1.oid=i.inhparent and i.inhrelid=c2.oid"\
980 " and (%d = pg_catalog.length('%s'))"\
981 " and pg_catalog.quote_ident(c1.relname)='%s'"\
982 " and pg_catalog.pg_table_is_visible(c2.oid)"\
983 " and c2.relispartition = 'true'"
986 * This is a list of all "things" in Pgsql, which can show up after CREATE or
987 * DROP; and there is also a query to get a list of them.
993 const char *query; /* simple query, or NULL */
994 const SchemaQuery *squery; /* schema query, or NULL */
995 const bits32 flags; /* visibility flags, see below */
998 #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
999 #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
1000 #define THING_NO_ALTER (1 << 2) /* should not show up after ALTER */
1001 #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
1003 static const pgsql_thing_t words_after_create[] = {
1004 {"ACCESS METHOD", NULL, NULL, THING_NO_ALTER},
1005 {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
1006 {"CAST", NULL, NULL}, /* Casts have complex structures for names, so
1008 {"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'"},
1011 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
1012 * to be used only by pg_dump.
1014 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
1015 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
1016 {"DATABASE", Query_for_list_of_databases},
1017 {"DEFAULT PRIVILEGES", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1018 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
1019 {"DOMAIN", NULL, &Query_for_list_of_domains},
1020 {"EVENT TRIGGER", NULL, NULL},
1021 {"EXTENSION", Query_for_list_of_extensions},
1022 {"FOREIGN DATA WRAPPER", NULL, NULL},
1023 {"FOREIGN TABLE", NULL, NULL},
1024 {"FUNCTION", NULL, &Query_for_list_of_functions},
1025 {"GROUP", Query_for_list_of_roles},
1026 {"INDEX", NULL, &Query_for_list_of_indexes},
1027 {"LANGUAGE", Query_for_list_of_languages},
1028 {"LARGE OBJECT", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1029 {"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
1030 {"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a
1032 {"OWNED", NULL, NULL, THING_NO_CREATE | THING_NO_ALTER}, /* for DROP OWNED BY ... */
1033 {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
1034 {"POLICY", NULL, NULL},
1035 {"PUBLICATION", Query_for_list_of_publications},
1036 {"ROLE", Query_for_list_of_roles},
1037 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
1038 {"SCHEMA", Query_for_list_of_schemas},
1039 {"SEQUENCE", NULL, &Query_for_list_of_sequences},
1040 {"SERVER", Query_for_list_of_servers},
1041 {"STATISTICS", NULL, &Query_for_list_of_statistics},
1042 {"SUBSCRIPTION", Query_for_list_of_subscriptions},
1043 {"SYSTEM", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1044 {"TABLE", NULL, &Query_for_list_of_tables},
1045 {"TABLESPACE", Query_for_list_of_tablespaces},
1046 {"TEMP", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE
1048 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
1049 {"TEMPORARY", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMPORARY
1051 {"TEXT SEARCH", NULL, NULL},
1052 {"TRANSFORM", NULL, NULL},
1053 {"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"},
1054 {"TYPE", NULL, &Query_for_list_of_datatypes},
1055 {"UNIQUE", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNIQUE
1057 {"UNLOGGED", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNLOGGED
1059 {"USER", Query_for_list_of_roles},
1060 {"USER MAPPING FOR", NULL, NULL},
1061 {"VIEW", NULL, &Query_for_list_of_views},
1062 {NULL} /* end of list */
1066 /* Forward declaration of functions */
1067 static char **psql_completion(const char *text, int start, int end);
1068 static char *create_command_generator(const char *text, int state);
1069 static char *drop_command_generator(const char *text, int state);
1070 static char *alter_command_generator(const char *text, int state);
1071 static char *complete_from_query(const char *text, int state);
1072 static char *complete_from_schema_query(const char *text, int state);
1073 static char *_complete_from_query(int is_schema_query,
1074 const char *text, int state);
1075 static char *complete_from_list(const char *text, int state);
1076 static char *complete_from_const(const char *text, int state);
1077 static void append_variable_names(char ***varnames, int *nvars,
1078 int *maxvars, const char *varname,
1079 const char *prefix, const char *suffix);
1080 static char **complete_from_variables(const char *text,
1081 const char *prefix, const char *suffix, bool need_value);
1082 static char *complete_from_files(const char *text, int state);
1084 static char *pg_strdup_keyword_case(const char *s, const char *ref);
1085 static char *escape_string(const char *text);
1086 static PGresult *exec_query(const char *query);
1088 static char **get_previous_words(int point, char **buffer, int *nwords);
1090 static char *get_guctype(const char *varname);
1093 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
1094 static char *dequote_file_name(char *text, char quote_char);
1099 * Initialize the readline library for our purposes.
1102 initialize_readline(void)
1104 rl_readline_name = (char *) pset.progname;
1105 rl_attempted_completion_function = psql_completion;
1107 rl_basic_word_break_characters = WORD_BREAKS;
1109 completion_max_records = 1000;
1112 * There is a variable rl_completion_query_items for this but apparently
1113 * it's not defined everywhere.
1118 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1119 * using case-insensitive or case-sensitive comparisons.
1121 * If pattern is NULL, it's a wild card that matches any word.
1122 * If pattern begins with '!', the result is negated, ie we check that 'word'
1123 * does *not* match any alternative appearing in the rest of 'pattern'.
1124 * Any alternative can end with '*' which is a wild card, i.e., it means
1125 * match any word that matches the characters so far. (We do not currently
1126 * support '*' elsewhere than the end of an alternative.)
1128 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1129 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1130 * just be written directly in patterns.)
1132 #define MatchAny NULL
1133 #define MatchAnyExcept(pattern) ("!" pattern)
1136 word_matches_internal(const char *pattern,
1138 bool case_sensitive)
1143 /* NULL pattern matches anything. */
1144 if (pattern == NULL)
1147 /* Handle negated patterns from the MatchAnyExcept macro. */
1148 if (*pattern == '!')
1149 return !word_matches_internal(pattern + 1, word, case_sensitive);
1151 /* Else consider each alternative in the pattern. */
1152 wordlen = strlen(word);
1157 /* Find end of current alternative. */
1159 while (*c != '\0' && *c != '|')
1161 /* Was there a wild card? (Assumes first alternative is not empty) */
1164 /* Yes, wildcard match? */
1165 patternlen = c - pattern - 1;
1166 if (wordlen >= patternlen &&
1168 strncmp(word, pattern, patternlen) == 0 :
1169 pg_strncasecmp(word, pattern, patternlen) == 0))
1174 /* No, plain match? */
1175 patternlen = c - pattern;
1176 if (wordlen == patternlen &&
1178 strncmp(word, pattern, wordlen) == 0 :
1179 pg_strncasecmp(word, pattern, wordlen) == 0))
1182 /* Out of alternatives? */
1185 /* Nope, try next alternative. */
1193 * There are enough matching calls below that it seems worth having these two
1194 * interface routines rather than including a third parameter in every call.
1196 * word_matches --- match case-insensitively.
1199 word_matches(const char *pattern, const char *word)
1201 return word_matches_internal(pattern, word, false);
1205 * word_matches_cs --- match case-sensitively.
1208 word_matches_cs(const char *pattern, const char *word)
1210 return word_matches_internal(pattern, word, true);
1214 * Check if the final character of 's' is 'c'.
1217 ends_with(const char *s, char c)
1219 size_t length = strlen(s);
1221 return (length > 0 && s[length - 1] == c);
1225 * The completion function.
1227 * According to readline spec this gets passed the text entered so far and its
1228 * start and end positions in the readline buffer. The return value is some
1229 * partially obscure list format that can be generated by readline's
1230 * completion_matches() function, so we don't have to worry about it.
1233 psql_completion(const char *text, int start, int end)
1235 /* This is the variable we'll return. */
1236 char **matches = NULL;
1238 /* Workspace for parsed words. */
1241 /* This array will contain pointers to parsed words. */
1242 char **previous_words;
1244 /* The number of words found on the input line. */
1245 int previous_words_count;
1248 * For compactness, we use these macros to reference previous_words[].
1249 * Caution: do not access a previous_words[] entry without having checked
1250 * previous_words_count to be sure it's valid. In most cases below, that
1251 * check is implicit in a TailMatches() or similar macro, but in some
1252 * places we have to check it explicitly.
1254 #define prev_wd (previous_words[0])
1255 #define prev2_wd (previous_words[1])
1256 #define prev3_wd (previous_words[2])
1257 #define prev4_wd (previous_words[3])
1258 #define prev5_wd (previous_words[4])
1259 #define prev6_wd (previous_words[5])
1260 #define prev7_wd (previous_words[6])
1261 #define prev8_wd (previous_words[7])
1262 #define prev9_wd (previous_words[8])
1264 /* Macros for matching the last N words before point, case-insensitively. */
1265 #define TailMatches1(p1) \
1266 (previous_words_count >= 1 && \
1267 word_matches(p1, prev_wd))
1269 #define TailMatches2(p2, p1) \
1270 (previous_words_count >= 2 && \
1271 word_matches(p1, prev_wd) && \
1272 word_matches(p2, prev2_wd))
1274 #define TailMatches3(p3, p2, p1) \
1275 (previous_words_count >= 3 && \
1276 word_matches(p1, prev_wd) && \
1277 word_matches(p2, prev2_wd) && \
1278 word_matches(p3, prev3_wd))
1280 #define TailMatches4(p4, p3, p2, p1) \
1281 (previous_words_count >= 4 && \
1282 word_matches(p1, prev_wd) && \
1283 word_matches(p2, prev2_wd) && \
1284 word_matches(p3, prev3_wd) && \
1285 word_matches(p4, prev4_wd))
1287 #define TailMatches5(p5, p4, p3, p2, p1) \
1288 (previous_words_count >= 5 && \
1289 word_matches(p1, prev_wd) && \
1290 word_matches(p2, prev2_wd) && \
1291 word_matches(p3, prev3_wd) && \
1292 word_matches(p4, prev4_wd) && \
1293 word_matches(p5, prev5_wd))
1295 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1296 (previous_words_count >= 6 && \
1297 word_matches(p1, prev_wd) && \
1298 word_matches(p2, prev2_wd) && \
1299 word_matches(p3, prev3_wd) && \
1300 word_matches(p4, prev4_wd) && \
1301 word_matches(p5, prev5_wd) && \
1302 word_matches(p6, prev6_wd))
1304 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1305 (previous_words_count >= 7 && \
1306 word_matches(p1, prev_wd) && \
1307 word_matches(p2, prev2_wd) && \
1308 word_matches(p3, prev3_wd) && \
1309 word_matches(p4, prev4_wd) && \
1310 word_matches(p5, prev5_wd) && \
1311 word_matches(p6, prev6_wd) && \
1312 word_matches(p7, prev7_wd))
1314 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1315 (previous_words_count >= 8 && \
1316 word_matches(p1, prev_wd) && \
1317 word_matches(p2, prev2_wd) && \
1318 word_matches(p3, prev3_wd) && \
1319 word_matches(p4, prev4_wd) && \
1320 word_matches(p5, prev5_wd) && \
1321 word_matches(p6, prev6_wd) && \
1322 word_matches(p7, prev7_wd) && \
1323 word_matches(p8, prev8_wd))
1325 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1326 (previous_words_count >= 9 && \
1327 word_matches(p1, prev_wd) && \
1328 word_matches(p2, prev2_wd) && \
1329 word_matches(p3, prev3_wd) && \
1330 word_matches(p4, prev4_wd) && \
1331 word_matches(p5, prev5_wd) && \
1332 word_matches(p6, prev6_wd) && \
1333 word_matches(p7, prev7_wd) && \
1334 word_matches(p8, prev8_wd) && \
1335 word_matches(p9, prev9_wd))
1337 /* Macros for matching the last N words before point, case-sensitively. */
1338 #define TailMatchesCS1(p1) \
1339 (previous_words_count >= 1 && \
1340 word_matches_cs(p1, prev_wd))
1341 #define TailMatchesCS2(p2, p1) \
1342 (previous_words_count >= 2 && \
1343 word_matches_cs(p1, prev_wd) && \
1344 word_matches_cs(p2, prev2_wd))
1345 #define TailMatchesCS3(p3, p2, p1) \
1346 (previous_words_count >= 3 && \
1347 word_matches_cs(p1, prev_wd) && \
1348 word_matches_cs(p2, prev2_wd) && \
1349 word_matches_cs(p3, prev3_wd))
1350 #define TailMatchesCS4(p4, p3, p2, p1) \
1351 (previous_words_count >= 4 && \
1352 word_matches_cs(p1, prev_wd) && \
1353 word_matches_cs(p2, prev2_wd) && \
1354 word_matches_cs(p3, prev3_wd) && \
1355 word_matches_cs(p4, prev4_wd))
1358 * Macros for matching N words beginning at the start of the line,
1359 * case-insensitively.
1361 #define Matches1(p1) \
1362 (previous_words_count == 1 && \
1364 #define Matches2(p1, p2) \
1365 (previous_words_count == 2 && \
1366 TailMatches2(p1, p2))
1367 #define Matches3(p1, p2, p3) \
1368 (previous_words_count == 3 && \
1369 TailMatches3(p1, p2, p3))
1370 #define Matches4(p1, p2, p3, p4) \
1371 (previous_words_count == 4 && \
1372 TailMatches4(p1, p2, p3, p4))
1373 #define Matches5(p1, p2, p3, p4, p5) \
1374 (previous_words_count == 5 && \
1375 TailMatches5(p1, p2, p3, p4, p5))
1376 #define Matches6(p1, p2, p3, p4, p5, p6) \
1377 (previous_words_count == 6 && \
1378 TailMatches6(p1, p2, p3, p4, p5, p6))
1379 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1380 (previous_words_count == 7 && \
1381 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1382 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1383 (previous_words_count == 8 && \
1384 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1385 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1386 (previous_words_count == 9 && \
1387 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1390 * Macros for matching N words at the start of the line, regardless of
1391 * what is after them, case-insensitively.
1393 #define HeadMatches1(p1) \
1394 (previous_words_count >= 1 && \
1395 word_matches(p1, previous_words[previous_words_count - 1]))
1397 #define HeadMatches2(p1, p2) \
1398 (previous_words_count >= 2 && \
1399 word_matches(p1, previous_words[previous_words_count - 1]) && \
1400 word_matches(p2, previous_words[previous_words_count - 2]))
1402 #define HeadMatches3(p1, p2, p3) \
1403 (previous_words_count >= 3 && \
1404 word_matches(p1, previous_words[previous_words_count - 1]) && \
1405 word_matches(p2, previous_words[previous_words_count - 2]) && \
1406 word_matches(p3, previous_words[previous_words_count - 3]))
1408 /* Known command-starting keywords. */
1409 static const char *const sql_commands[] = {
1410 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
1411 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1412 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1413 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1414 "MOVE", "NOTIFY", "PREPARE",
1415 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1416 "RESET", "REVOKE", "ROLLBACK",
1417 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1418 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1422 /* psql's backslash commands. */
1423 static const char *const backslash_commands[] = {
1425 "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1426 "\\copyright", "\\crosstabview",
1427 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1428 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1429 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1430 "\\dm", "\\dn", "\\do", "\\dO", "\\dp",
1431 "\\drds", "\\dRs", "\\dRp", "\\ds", "\\dS",
1432 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1433 "\\e", "\\echo", "\\ef", "\\elif", "\\else", "\\encoding",
1434 "\\endif", "\\errverbose", "\\ev",
1436 "\\g", "\\gexec", "\\gset", "\\gx",
1437 "\\h", "\\help", "\\H",
1438 "\\i", "\\if", "\\ir",
1439 "\\l", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1441 "\\p", "\\password", "\\prompt", "\\pset",
1444 "\\s", "\\set", "\\setenv", "\\sf", "\\sv",
1445 "\\t", "\\T", "\\timing",
1454 (void) end; /* "end" is not used */
1456 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1457 rl_completion_append_character = ' ';
1460 /* Clear a few things. */
1461 completion_charp = NULL;
1462 completion_charpp = NULL;
1463 completion_info_charp = NULL;
1464 completion_info_charp2 = NULL;
1467 * Scan the input line to extract the words before our current position.
1468 * According to those we'll make some smart decisions on what the user is
1469 * probably intending to type.
1471 previous_words = get_previous_words(start,
1473 &previous_words_count);
1475 /* If current word is a backslash command, offer completions for that */
1476 if (text[0] == '\\')
1477 COMPLETE_WITH_LIST_CS(backslash_commands);
1479 /* If current word is a variable interpolation, handle that case */
1480 else if (text[0] == ':' && text[1] != ':')
1482 if (text[1] == '\'')
1483 matches = complete_from_variables(text, ":'", "'", true);
1484 else if (text[1] == '"')
1485 matches = complete_from_variables(text, ":\"", "\"", true);
1487 matches = complete_from_variables(text, ":", "", true);
1490 /* If no previous word, suggest one of the basic sql commands */
1491 else if (previous_words_count == 0)
1492 COMPLETE_WITH_LIST(sql_commands);
1495 /* complete with something you can create */
1496 else if (TailMatches1("CREATE"))
1497 matches = completion_matches(text, create_command_generator);
1499 /* DROP, but not DROP embedded in other commands */
1500 /* complete with something you can drop */
1501 else if (Matches1("DROP"))
1502 matches = completion_matches(text, drop_command_generator);
1507 else if (Matches2("ALTER", "TABLE"))
1508 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1509 "UNION SELECT 'ALL IN TABLESPACE'");
1511 /* ALTER something */
1512 else if (Matches1("ALTER"))
1513 matches = completion_matches(text, alter_command_generator);
1514 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1515 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1516 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1517 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1518 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1519 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1520 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1521 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1522 COMPLETE_WITH_CONST("SET TABLESPACE");
1523 /* ALTER AGGREGATE,FUNCTION <name> */
1524 else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1525 COMPLETE_WITH_CONST("(");
1526 /* ALTER AGGREGATE,FUNCTION <name> (...) */
1527 else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1529 if (ends_with(prev_wd, ')'))
1530 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1532 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1534 /* ALTER PUBLICATION <name> */
1535 else if (Matches3("ALTER", "PUBLICATION", MatchAny))
1537 COMPLETE_WITH_LIST5("ADD TABLE", "DROP TABLE", "OWNER TO", "RENAME TO", "SET");
1539 /* ALTER PUBLICATION <name> SET */
1540 else if (Matches4("ALTER", "PUBLICATION", MatchAny, "SET"))
1542 COMPLETE_WITH_LIST2("(", "TABLE");
1544 /* ALTER PUBLICATION <name> SET ( */
1545 else if (HeadMatches3("ALTER", "PUBLICATION", MatchAny) && TailMatches2("SET", "("))
1547 COMPLETE_WITH_CONST("publish");
1549 /* ALTER SUBSCRIPTION <name> */
1550 else if (Matches3("ALTER", "SUBSCRIPTION", MatchAny))
1552 COMPLETE_WITH_LIST7("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
1553 "RENAME TO", "REFRESH PUBLICATION", "SET");
1555 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION */
1556 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1557 TailMatches2("REFRESH", "PUBLICATION"))
1559 COMPLETE_WITH_CONST("WITH (");
1561 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
1562 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1563 TailMatches4("REFRESH", "PUBLICATION", "WITH", "("))
1565 COMPLETE_WITH_CONST("copy_data");
1567 /* ALTER SUBSCRIPTION <name> SET */
1568 else if (Matches4("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
1570 COMPLETE_WITH_LIST2("(", "PUBLICATION");
1572 /* ALTER SUBSCRIPTION <name> SET ( */
1573 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "("))
1575 COMPLETE_WITH_LIST2("slot_name", "synchronous_commit");
1577 /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
1578 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "PUBLICATION"))
1580 /* complete with nothing here as this refers to remote publications */
1582 /* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> */
1583 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1584 TailMatches3("SET", "PUBLICATION", MatchAny))
1586 COMPLETE_WITH_CONST("WITH (");
1588 /* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> WITH ( */
1589 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1590 TailMatches5("SET", "PUBLICATION", MatchAny, "WITH", "("))
1592 COMPLETE_WITH_LIST2("copy_data", "refresh");
1594 /* ALTER SCHEMA <name> */
1595 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1596 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1598 /* ALTER COLLATION <name> */
1599 else if (Matches3("ALTER", "COLLATION", MatchAny))
1600 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1602 /* ALTER CONVERSION <name> */
1603 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1604 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1606 /* ALTER DATABASE <name> */
1607 else if (Matches3("ALTER", "DATABASE", MatchAny))
1608 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1609 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1610 "CONNECTION LIMIT");
1612 /* ALTER EVENT TRIGGER */
1613 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1614 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1616 /* ALTER EVENT TRIGGER <name> */
1617 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1618 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1620 /* ALTER EVENT TRIGGER <name> ENABLE */
1621 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1622 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1624 /* ALTER EXTENSION <name> */
1625 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1626 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1628 /* ALTER EXTENSION <name> UPDATE */
1629 else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
1631 completion_info_charp = prev2_wd;
1632 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
1635 /* ALTER EXTENSION <name> UPDATE TO */
1636 else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
1638 completion_info_charp = prev3_wd;
1639 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
1643 else if (Matches2("ALTER", "FOREIGN"))
1644 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1646 /* ALTER FOREIGN DATA WRAPPER <name> */
1647 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1648 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1650 /* ALTER FOREIGN TABLE <name> */
1651 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1653 static const char *const list_ALTER_FOREIGN_TABLE[] =
1654 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1655 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1656 "VALIDATE CONSTRAINT", NULL};
1658 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1662 else if (Matches2("ALTER", "INDEX"))
1663 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1664 "UNION SELECT 'ALL IN TABLESPACE'");
1665 /* ALTER INDEX <name> */
1666 else if (Matches3("ALTER", "INDEX", MatchAny))
1667 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1668 /* ALTER INDEX <name> SET */
1669 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1670 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1671 /* ALTER INDEX <name> RESET */
1672 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1673 COMPLETE_WITH_CONST("(");
1674 /* ALTER INDEX <foo> SET|RESET ( */
1675 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1676 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1677 "gin_pending_list_limit");
1678 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1679 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1680 "gin_pending_list_limit =");
1682 /* ALTER LANGUAGE <name> */
1683 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1684 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1686 /* ALTER LARGE OBJECT <oid> */
1687 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1688 COMPLETE_WITH_CONST("OWNER TO");
1690 /* ALTER MATERIALIZED VIEW */
1691 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1692 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1693 "UNION SELECT 'ALL IN TABLESPACE'");
1695 /* ALTER USER,ROLE <name> */
1696 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1697 !TailMatches2("USER", "MAPPING"))
1699 static const char *const list_ALTERUSER[] =
1700 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1701 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1702 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1703 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1704 "REPLICATION", "RESET", "SET", "SUPERUSER",
1705 "VALID UNTIL", "WITH", NULL};
1707 COMPLETE_WITH_LIST(list_ALTERUSER);
1710 /* ALTER USER,ROLE <name> WITH */
1711 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1713 /* Similar to the above, but don't complete "WITH" again. */
1714 static const char *const list_ALTERUSER_WITH[] =
1715 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1716 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1717 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1718 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1719 "REPLICATION", "RESET", "SET", "SUPERUSER",
1720 "VALID UNTIL", NULL};
1722 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1725 /* ALTER DEFAULT PRIVILEGES */
1726 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1727 COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
1728 /* ALTER DEFAULT PRIVILEGES FOR */
1729 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1730 COMPLETE_WITH_CONST("ROLE");
1731 /* ALTER DEFAULT PRIVILEGES IN */
1732 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1733 COMPLETE_WITH_CONST("SCHEMA");
1734 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1735 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1737 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
1738 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1739 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1741 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
1742 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1743 else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1745 COMPLETE_WITH_CONST("ROLE");
1746 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
1747 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1748 else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1749 MatchAny, "IN", "SCHEMA", MatchAny) ||
1750 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1751 MatchAny, "FOR", "ROLE|USER", MatchAny))
1752 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1753 /* ALTER DOMAIN <name> */
1754 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1755 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1756 "VALIDATE CONSTRAINT");
1757 /* ALTER DOMAIN <sth> DROP */
1758 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1759 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1760 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1761 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1763 completion_info_charp = prev3_wd;
1764 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1766 /* ALTER DOMAIN <sth> RENAME */
1767 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1768 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1769 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1770 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1771 COMPLETE_WITH_CONST("TO");
1773 /* ALTER DOMAIN <sth> SET */
1774 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1775 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1776 /* ALTER SEQUENCE <name> */
1777 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1779 static const char *const list_ALTERSEQUENCE[] =
1780 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1781 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1783 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1785 /* ALTER SEQUENCE <name> NO */
1786 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1787 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1788 /* ALTER SERVER <name> */
1789 else if (Matches3("ALTER", "SERVER", MatchAny))
1790 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1791 /* ALTER SERVER <name> VERSION <version> */
1792 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1793 COMPLETE_WITH_CONST("OPTIONS");
1794 /* ALTER SYSTEM SET, RESET, RESET ALL */
1795 else if (Matches2("ALTER", "SYSTEM"))
1796 COMPLETE_WITH_LIST2("SET", "RESET");
1797 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1798 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1799 else if (Matches4("ALTER", "SYSTEM", "SET", MatchAny))
1800 COMPLETE_WITH_CONST("TO");
1801 /* ALTER VIEW <name> */
1802 else if (Matches3("ALTER", "VIEW", MatchAny))
1803 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1805 /* ALTER MATERIALIZED VIEW <name> */
1806 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1807 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1810 /* ALTER POLICY <name> */
1811 else if (Matches2("ALTER", "POLICY"))
1812 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1813 /* ALTER POLICY <name> ON */
1814 else if (Matches3("ALTER", "POLICY", MatchAny))
1815 COMPLETE_WITH_CONST("ON");
1816 /* ALTER POLICY <name> ON <table> */
1817 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1819 completion_info_charp = prev2_wd;
1820 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1822 /* ALTER POLICY <name> ON <table> - show options */
1823 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1824 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1825 /* ALTER POLICY <name> ON <table> TO <role> */
1826 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1827 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1828 /* ALTER POLICY <name> ON <table> USING ( */
1829 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1830 COMPLETE_WITH_CONST("(");
1831 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1832 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1833 COMPLETE_WITH_CONST("(");
1835 /* ALTER RULE <name>, add ON */
1836 else if (Matches3("ALTER", "RULE", MatchAny))
1837 COMPLETE_WITH_CONST("ON");
1839 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1840 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1842 completion_info_charp = prev2_wd;
1843 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1846 /* ALTER RULE <name> ON <name> */
1847 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1848 COMPLETE_WITH_CONST("RENAME TO");
1850 /* ALTER STATISTICS <name> */
1851 else if (Matches3("ALTER", "STATISTICS", MatchAny))
1852 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1854 /* ALTER TRIGGER <name>, add ON */
1855 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1856 COMPLETE_WITH_CONST("ON");
1858 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1860 completion_info_charp = prev2_wd;
1861 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1865 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1867 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1868 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1870 /* ALTER TRIGGER <name> ON <name> */
1871 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1872 COMPLETE_WITH_CONST("RENAME TO");
1875 * If we detect ALTER TABLE <name>, suggest sub commands
1877 else if (Matches3("ALTER", "TABLE", MatchAny))
1879 static const char *const list_ALTER2[] =
1880 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1881 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1882 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", "ATTACH PARTITION",
1883 "DETACH PARTITION", NULL};
1885 COMPLETE_WITH_LIST(list_ALTER2);
1887 /* ALTER TABLE xxx ENABLE */
1888 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1889 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1891 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1892 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1893 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1895 completion_info_charp = prev3_wd;
1896 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1898 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1900 completion_info_charp = prev4_wd;
1901 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1903 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1905 completion_info_charp = prev3_wd;
1906 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1908 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1910 completion_info_charp = prev4_wd;
1911 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1913 /* ALTER TABLE xxx INHERIT */
1914 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1915 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1916 /* ALTER TABLE xxx NO INHERIT */
1917 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1918 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1919 /* ALTER TABLE xxx DISABLE */
1920 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1921 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1922 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1924 completion_info_charp = prev3_wd;
1925 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1927 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1929 completion_info_charp = prev3_wd;
1930 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1933 /* ALTER TABLE xxx ALTER */
1934 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1935 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1937 /* ALTER TABLE xxx RENAME */
1938 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1939 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1940 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1941 COMPLETE_WITH_ATTR(prev3_wd, "");
1943 /* ALTER TABLE xxx RENAME yyy */
1944 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1945 COMPLETE_WITH_CONST("TO");
1947 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1948 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1949 COMPLETE_WITH_CONST("TO");
1951 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1952 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1953 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1954 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1955 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1956 COMPLETE_WITH_ATTR(prev3_wd, "");
1959 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1960 * provide list of constraints
1962 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1964 completion_info_charp = prev3_wd;
1965 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1967 /* ALTER TABLE ALTER [COLUMN] <foo> */
1968 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1969 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1970 COMPLETE_WITH_LIST6("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
1971 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1972 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1973 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1974 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1975 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1976 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1977 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1978 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1979 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1980 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1981 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1982 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1983 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1984 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1985 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1986 COMPLETE_WITH_LIST3("DEFAULT", "IDENTITY", "NOT NULL");
1987 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1988 COMPLETE_WITH_CONST("ON");
1989 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1991 completion_info_charp = prev3_wd;
1992 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1994 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1995 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1996 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
2000 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
2003 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
2004 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2005 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
2006 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
2007 COMPLETE_WITH_CONST("OIDS");
2008 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
2009 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
2010 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
2011 /* ALTER TABLE <foo> RESET */
2012 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
2013 COMPLETE_WITH_CONST("(");
2014 /* ALTER TABLE <foo> SET|RESET ( */
2015 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
2017 static const char *const list_TABLEOPTIONS[] =
2019 "autovacuum_analyze_scale_factor",
2020 "autovacuum_analyze_threshold",
2021 "autovacuum_enabled",
2022 "autovacuum_freeze_max_age",
2023 "autovacuum_freeze_min_age",
2024 "autovacuum_freeze_table_age",
2025 "autovacuum_multixact_freeze_max_age",
2026 "autovacuum_multixact_freeze_min_age",
2027 "autovacuum_multixact_freeze_table_age",
2028 "autovacuum_vacuum_cost_delay",
2029 "autovacuum_vacuum_cost_limit",
2030 "autovacuum_vacuum_scale_factor",
2031 "autovacuum_vacuum_threshold",
2034 "log_autovacuum_min_duration",
2035 "toast.autovacuum_enabled",
2036 "toast.autovacuum_freeze_max_age",
2037 "toast.autovacuum_freeze_min_age",
2038 "toast.autovacuum_freeze_table_age",
2039 "toast.autovacuum_multixact_freeze_max_age",
2040 "toast.autovacuum_multixact_freeze_min_age",
2041 "toast.autovacuum_multixact_freeze_table_age",
2042 "toast.autovacuum_vacuum_cost_delay",
2043 "toast.autovacuum_vacuum_cost_limit",
2044 "toast.autovacuum_vacuum_scale_factor",
2045 "toast.autovacuum_vacuum_threshold",
2046 "toast.log_autovacuum_min_duration",
2047 "user_catalog_table",
2051 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
2053 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
2055 completion_info_charp = prev5_wd;
2056 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2058 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
2059 COMPLETE_WITH_CONST("INDEX");
2060 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
2061 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
2062 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
2063 COMPLETE_WITH_CONST("IDENTITY");
2066 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
2069 else if (Matches5("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
2070 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2071 /* Limited completion support for partition bound specification */
2072 else if (TailMatches3("ATTACH", "PARTITION", MatchAny))
2073 COMPLETE_WITH_CONST("FOR VALUES");
2074 else if (TailMatches2("FOR", "VALUES"))
2075 COMPLETE_WITH_LIST2("FROM (", "IN (");
2078 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
2079 * partitions of <foo>.
2081 else if (Matches5("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
2083 completion_info_charp = prev3_wd;
2084 COMPLETE_WITH_QUERY(Query_for_partition_of_table);
2087 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
2088 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
2089 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
2090 /* ALTER TABLESPACE <foo> SET|RESET */
2091 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
2092 COMPLETE_WITH_CONST("(");
2093 /* ALTER TABLESPACE <foo> SET|RESET ( */
2094 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
2095 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
2096 "effective_io_concurrency");
2098 /* ALTER TEXT SEARCH */
2099 else if (Matches3("ALTER", "TEXT", "SEARCH"))
2100 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2101 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
2102 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
2103 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
2104 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
2105 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2106 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
2108 "OWNER TO", "RENAME TO", "SET SCHEMA");
2110 /* complete ALTER TYPE <foo> with actions */
2111 else if (Matches3("ALTER", "TYPE", MatchAny))
2112 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
2114 "OWNER TO", "RENAME", "SET SCHEMA");
2115 /* complete ALTER TYPE <foo> ADD with actions */
2116 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
2117 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
2118 /* ALTER TYPE <foo> RENAME */
2119 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
2120 COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
2121 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
2122 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
2123 COMPLETE_WITH_CONST("TO");
2126 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
2129 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
2130 COMPLETE_WITH_ATTR(prev3_wd, "");
2131 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
2132 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
2133 COMPLETE_WITH_CONST("TYPE");
2134 /* complete ALTER GROUP <foo> */
2135 else if (Matches3("ALTER", "GROUP", MatchAny))
2136 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
2137 /* complete ALTER GROUP <foo> ADD|DROP with USER */
2138 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
2139 COMPLETE_WITH_CONST("USER");
2140 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
2141 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
2142 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2145 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
2147 else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
2148 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
2151 else if (Matches1("BEGIN"))
2152 COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2154 else if (Matches1("END|ABORT"))
2155 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
2157 else if (Matches1("COMMIT"))
2158 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
2159 /* RELEASE SAVEPOINT */
2160 else if (Matches1("RELEASE"))
2161 COMPLETE_WITH_CONST("SAVEPOINT");
2163 else if (Matches1("ROLLBACK"))
2164 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
2166 else if (Matches1("CLUSTER"))
2167 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
2168 else if (Matches2("CLUSTER", "VERBOSE"))
2169 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2170 /* If we have CLUSTER <sth>, then add "USING" */
2171 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
2172 COMPLETE_WITH_CONST("USING");
2173 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
2174 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
2175 COMPLETE_WITH_CONST("USING");
2176 /* If we have CLUSTER <sth> USING, then add the index as well */
2177 else if (Matches3("CLUSTER", MatchAny, "USING") ||
2178 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
2180 completion_info_charp = prev2_wd;
2181 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2185 else if (Matches1("COMMENT"))
2186 COMPLETE_WITH_CONST("ON");
2187 else if (Matches2("COMMENT", "ON"))
2189 static const char *const list_COMMENT[] =
2190 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
2191 "EVENT TRIGGER", "EXTENSION",
2192 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2193 "SERVER", "INDEX", "LANGUAGE", "POLICY", "PUBLICATION", "RULE",
2194 "SCHEMA", "SEQUENCE", "STATISTICS", "SUBSCRIPTION",
2195 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
2196 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
2197 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
2199 COMPLETE_WITH_LIST(list_COMMENT);
2201 else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
2202 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2203 else if (Matches3("COMMENT", "ON", "FOREIGN"))
2204 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2205 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
2206 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2207 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
2208 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
2209 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
2210 COMPLETE_WITH_CONST("ON");
2211 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2213 completion_info_charp = prev2_wd;
2214 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
2216 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
2217 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2218 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
2219 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2220 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
2221 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2222 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
2223 COMPLETE_WITH_CONST("IS");
2228 * If we have COPY, offer list of tables or "(" (Also cover the analogous
2229 * backslash command).
2231 else if (Matches1("COPY|\\copy"))
2232 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2233 " UNION ALL SELECT '('");
2234 /* If we have COPY BINARY, complete with list of tables */
2235 else if (Matches2("COPY", "BINARY"))
2236 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2237 /* If we have COPY (, complete it with legal commands */
2238 else if (Matches2("COPY|\\copy", "("))
2239 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
2240 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
2241 else if (Matches2("COPY|\\copy", MatchAny) ||
2242 Matches3("COPY", "BINARY", MatchAny))
2243 COMPLETE_WITH_LIST2("FROM", "TO");
2244 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
2245 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
2246 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
2248 completion_charp = "";
2249 matches = completion_matches(text, complete_from_files);
2252 /* Handle COPY [BINARY] <sth> FROM|TO filename */
2253 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
2254 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
2255 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
2258 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
2259 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
2260 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
2261 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
2264 /* CREATE ACCESS METHOD */
2265 /* Complete "CREATE ACCESS METHOD <name>" */
2266 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
2267 COMPLETE_WITH_CONST("TYPE");
2268 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
2269 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
2270 COMPLETE_WITH_CONST("INDEX");
2271 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
2272 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
2273 COMPLETE_WITH_CONST("HANDLER");
2275 /* CREATE DATABASE */
2276 else if (Matches3("CREATE", "DATABASE", MatchAny))
2277 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2279 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2280 "LC_COLLATE", "LC_CTYPE");
2282 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2283 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2285 /* CREATE EXTENSION */
2286 /* Complete with available extensions rather than installed ones. */
2287 else if (Matches2("CREATE", "EXTENSION"))
2288 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2289 /* CREATE EXTENSION <name> */
2290 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2291 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2292 /* CREATE EXTENSION <name> VERSION */
2293 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2295 completion_info_charp = prev2_wd;
2296 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2299 /* CREATE FOREIGN */
2300 else if (Matches2("CREATE", "FOREIGN"))
2301 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2303 /* CREATE FOREIGN DATA WRAPPER */
2304 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2305 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2307 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2308 /* First off we complete CREATE UNIQUE with "INDEX" */
2309 else if (TailMatches2("CREATE", "UNIQUE"))
2310 COMPLETE_WITH_CONST("INDEX");
2313 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2316 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2317 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2318 " UNION SELECT 'ON'"
2319 " UNION SELECT 'CONCURRENTLY'");
2320 /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
2321 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2322 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2323 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2326 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2329 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2330 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2331 " UNION SELECT 'ON'");
2332 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2333 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2334 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2335 COMPLETE_WITH_CONST("ON");
2338 * Complete INDEX <name> ON <table> with a list of table columns (which
2339 * should really be in parens)
2341 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2342 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2343 COMPLETE_WITH_LIST2("(", "USING");
2344 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2345 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2346 COMPLETE_WITH_ATTR(prev2_wd, "");
2347 /* same if you put in USING */
2348 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2349 COMPLETE_WITH_ATTR(prev4_wd, "");
2350 /* Complete USING with an index method */
2351 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2352 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2353 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2354 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2355 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2356 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2357 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2358 COMPLETE_WITH_CONST("(");
2361 /* Complete "CREATE POLICY <name> ON" */
2362 else if (Matches3("CREATE", "POLICY", MatchAny))
2363 COMPLETE_WITH_CONST("ON");
2364 /* Complete "CREATE POLICY <name> ON <table>" */
2365 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2366 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2367 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
2368 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2369 COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
2370 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
2371 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
2372 COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
2375 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2376 * FOR|TO|USING|WITH CHECK
2378 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
2379 COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
2380 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2381 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2382 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2383 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2384 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2385 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2386 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2387 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2388 COMPLETE_WITH_LIST2("TO", "USING (");
2389 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2390 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2391 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2392 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2393 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2394 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2395 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2396 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2397 COMPLETE_WITH_CONST("(");
2400 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2401 * ALL|SELECT|INSERT|UPDATE|DELETE
2403 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
2404 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2407 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2408 * INSERT TO|WITH CHECK"
2410 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
2411 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2414 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2415 * SELECT|DELETE TO|USING"
2417 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
2418 COMPLETE_WITH_LIST2("TO", "USING (");
2421 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2422 * ALL|UPDATE TO|USING|WITH CHECK
2424 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
2425 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2428 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
2431 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
2432 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2435 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2438 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
2439 COMPLETE_WITH_CONST("(");
2442 /* CREATE PUBLICATION */
2443 else if (Matches3("CREATE", "PUBLICATION", MatchAny))
2444 COMPLETE_WITH_LIST3("FOR TABLE", "FOR ALL TABLES", "WITH (");
2445 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR"))
2446 COMPLETE_WITH_LIST2("TABLE", "ALL TABLES");
2447 /* Complete "CREATE PUBLICATION <name> FOR TABLE <table>" */
2448 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
2449 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2450 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
2451 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
2452 COMPLETE_WITH_CONST("publish");
2455 /* Complete "CREATE RULE <sth>" with "AS ON" */
2456 else if (Matches3("CREATE", "RULE", MatchAny))
2457 COMPLETE_WITH_CONST("AS ON");
2458 /* Complete "CREATE RULE <sth> AS" with "ON" */
2459 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2460 COMPLETE_WITH_CONST("ON");
2461 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2462 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2463 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2464 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2465 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2466 COMPLETE_WITH_CONST("TO");
2467 /* Complete "AS ON <sth> TO" with a table name */
2468 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2469 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2471 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2472 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2473 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2474 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2475 "CYCLE", "OWNED BY", "START WITH");
2476 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2477 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2478 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2480 /* CREATE SERVER <name> */
2481 else if (Matches3("CREATE", "SERVER", MatchAny))
2482 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2484 /* CREATE STATISTICS <name> */
2485 else if (Matches3("CREATE", "STATISTICS", MatchAny))
2486 COMPLETE_WITH_LIST2("(", "ON");
2487 else if (Matches4("CREATE", "STATISTICS", MatchAny, "("))
2488 COMPLETE_WITH_LIST2("ndistinct", "dependencies");
2489 else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
2490 previous_words[0][0] == '(' &&
2491 previous_words[0][strlen(previous_words[0]) - 1] == ')')
2492 COMPLETE_WITH_CONST("ON");
2493 else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
2494 TailMatches1("FROM"))
2495 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2497 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2498 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2499 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2500 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2501 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2502 else if (TailMatches2("CREATE", "UNLOGGED"))
2503 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2504 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
2505 else if (TailMatches2("PARTITION", "BY"))
2506 COMPLETE_WITH_LIST2("RANGE (", "LIST (");
2507 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
2508 else if (TailMatches2("PARTITION", "OF"))
2509 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables, "");
2510 /* Limited completion support for partition bound specification */
2511 else if (TailMatches3("PARTITION", "OF", MatchAny))
2512 COMPLETE_WITH_CONST("FOR VALUES");
2514 /* CREATE TABLESPACE */
2515 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2516 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2517 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2518 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2519 COMPLETE_WITH_CONST("LOCATION");
2521 /* CREATE TEXT SEARCH */
2522 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2523 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2524 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2525 COMPLETE_WITH_CONST("(");
2527 /* CREATE SUBSCRIPTION */
2528 else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
2529 COMPLETE_WITH_CONST("CONNECTION");
2530 else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
2531 COMPLETE_WITH_CONST("PUBLICATION");
2532 else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
2533 MatchAny, "PUBLICATION"))
2535 /* complete with nothing here as this refers to remote publications */
2537 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("PUBLICATION", MatchAny))
2538 COMPLETE_WITH_CONST("WITH (");
2539 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
2540 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
2541 COMPLETE_WITH_LIST6("copy_data", "connect", "create_slot", "enabled",
2542 "slot_name", "synchronous_commit");
2544 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2545 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2546 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2547 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2548 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2549 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2550 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2551 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2552 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2553 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2554 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2555 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2556 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2557 COMPLETE_WITH_LIST2("ON", "OR");
2560 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2563 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2564 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2565 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2566 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2567 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2568 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
2569 COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
2570 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2571 else if (HeadMatches2("CREATE", "TRIGGER") &&
2572 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
2573 COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2574 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
2575 COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
2576 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
2577 COMPLETE_WITH_CONST("AS");
2578 else if (HeadMatches2("CREATE", "TRIGGER") &&
2579 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
2580 TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
2581 COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2582 else if (HeadMatches2("CREATE", "TRIGGER") &&
2583 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
2584 TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
2585 COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2586 else if (HeadMatches2("CREATE", "TRIGGER") &&
2587 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2588 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2589 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
2590 TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
2591 COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
2592 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
2593 COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
2594 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
2595 COMPLETE_WITH_LIST2("ROW", "STATEMENT");
2596 else if (HeadMatches2("CREATE", "TRIGGER") &&
2597 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
2598 TailMatches2("FOR", "ROW|STATEMENT")))
2599 COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
2600 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2601 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2602 COMPLETE_WITH_CONST("PROCEDURE");
2603 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
2604 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2606 /* CREATE ROLE,USER,GROUP <name> */
2607 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2608 !TailMatches2("USER", "MAPPING"))
2610 static const char *const list_CREATEROLE[] =
2611 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2612 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2613 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2614 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2615 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2616 "VALID UNTIL", "WITH", NULL};
2618 COMPLETE_WITH_LIST(list_CREATEROLE);
2621 /* CREATE ROLE,USER,GROUP <name> WITH */
2622 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2624 /* Similar to the above, but don't complete "WITH" again. */
2625 static const char *const list_CREATEROLE_WITH[] =
2626 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2627 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2628 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2629 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2630 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2631 "VALID UNTIL", NULL};
2633 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2636 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2637 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2638 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2640 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2641 /* Complete CREATE VIEW <name> with AS */
2642 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2643 COMPLETE_WITH_CONST("AS");
2644 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2645 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2646 COMPLETE_WITH_CONST("SELECT");
2648 /* CREATE MATERIALIZED VIEW */
2649 else if (Matches2("CREATE", "MATERIALIZED"))
2650 COMPLETE_WITH_CONST("VIEW");
2651 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2652 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2653 COMPLETE_WITH_CONST("AS");
2654 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2655 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2656 COMPLETE_WITH_CONST("SELECT");
2658 /* CREATE EVENT TRIGGER */
2659 else if (Matches2("CREATE", "EVENT"))
2660 COMPLETE_WITH_CONST("TRIGGER");
2661 /* Complete CREATE EVENT TRIGGER <name> with ON */
2662 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2663 COMPLETE_WITH_CONST("ON");
2664 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2665 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2666 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2669 else if (Matches1("DEALLOCATE"))
2670 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2673 else if (Matches2("DECLARE", MatchAny))
2674 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2676 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2677 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2679 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2680 /* ... despite which, only complete DELETE with FROM at start of line */
2681 else if (Matches1("DELETE"))
2682 COMPLETE_WITH_CONST("FROM");
2683 /* Complete DELETE FROM with a list of tables */
2684 else if (TailMatches2("DELETE", "FROM"))
2685 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2686 /* Complete DELETE FROM <table> */
2687 else if (TailMatches3("DELETE", "FROM", MatchAny))
2688 COMPLETE_WITH_LIST2("USING", "WHERE");
2689 /* XXX: implement tab completion for DELETE ... USING */
2692 else if (Matches1("DISCARD"))
2693 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2696 else if (Matches1("DO"))
2697 COMPLETE_WITH_CONST("LANGUAGE");
2700 /* Complete DROP object with CASCADE / RESTRICT */
2701 else if (Matches3("DROP",
2702 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
2704 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2705 (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2706 ends_with(prev_wd, ')')) ||
2707 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2708 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2709 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2710 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2711 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2713 /* help completing some of the variants */
2714 else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2715 COMPLETE_WITH_CONST("(");
2716 else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2717 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2718 else if (Matches2("DROP", "FOREIGN"))
2719 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2722 else if (Matches2("DROP", "INDEX"))
2723 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2724 " UNION SELECT 'CONCURRENTLY'");
2725 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2726 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2727 else if (Matches3("DROP", "INDEX", MatchAny))
2728 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2729 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2730 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2732 /* DROP MATERIALIZED VIEW */
2733 else if (Matches2("DROP", "MATERIALIZED"))
2734 COMPLETE_WITH_CONST("VIEW");
2735 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2736 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2739 else if (Matches2("DROP", "OWNED"))
2740 COMPLETE_WITH_CONST("BY");
2741 else if (Matches3("DROP", "OWNED", "BY"))
2742 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2744 /* DROP TEXT SEARCH */
2745 else if (Matches3("DROP", "TEXT", "SEARCH"))
2746 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2749 else if (Matches3("DROP", "TRIGGER", MatchAny))
2750 COMPLETE_WITH_CONST("ON");
2751 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2753 completion_info_charp = prev2_wd;
2754 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2756 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2757 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2759 /* DROP ACCESS METHOD */
2760 else if (Matches2("DROP", "ACCESS"))
2761 COMPLETE_WITH_CONST("METHOD");
2762 else if (Matches3("DROP", "ACCESS", "METHOD"))
2763 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2765 /* DROP EVENT TRIGGER */
2766 else if (Matches2("DROP", "EVENT"))
2767 COMPLETE_WITH_CONST("TRIGGER");
2768 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2769 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2771 /* DROP POLICY <name> */
2772 else if (Matches2("DROP", "POLICY"))
2773 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2774 /* DROP POLICY <name> ON */
2775 else if (Matches3("DROP", "POLICY", MatchAny))
2776 COMPLETE_WITH_CONST("ON");
2777 /* DROP POLICY <name> ON <table> */
2778 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2780 completion_info_charp = prev2_wd;
2781 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2785 else if (Matches3("DROP", "RULE", MatchAny))
2786 COMPLETE_WITH_CONST("ON");
2787 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2789 completion_info_charp = prev2_wd;
2790 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2792 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2793 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2796 else if (Matches1("EXECUTE"))
2797 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2802 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2804 else if (Matches1("EXPLAIN"))
2805 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2806 "ANALYZE", "VERBOSE");
2807 else if (Matches2("EXPLAIN", "ANALYZE"))
2808 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2810 else if (Matches2("EXPLAIN", "VERBOSE") ||
2811 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2812 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2815 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2816 else if (Matches1("FETCH|MOVE"))
2817 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2818 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2819 else if (Matches2("FETCH|MOVE", MatchAny))
2820 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2823 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2824 * but we may as well tab-complete both: perhaps some users prefer one
2825 * variant or the other.
2827 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2828 COMPLETE_WITH_LIST2("FROM", "IN");
2830 /* FOREIGN DATA WRAPPER */
2831 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2832 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2833 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2834 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2835 /* applies in CREATE SERVER */
2836 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2837 HeadMatches2("CREATE", "SERVER"))
2838 COMPLETE_WITH_CONST("OPTIONS");
2841 else if (TailMatches2("FOREIGN", "TABLE") &&
2842 !TailMatches3("CREATE", MatchAny, MatchAny))
2843 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2845 /* FOREIGN SERVER */
2846 else if (TailMatches2("FOREIGN", "SERVER"))
2847 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2850 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
2851 * ALTER DEFAULT PRIVILEGES, so use TailMatches
2853 /* Complete GRANT/REVOKE with a list of roles and privileges */
2854 else if (TailMatches1("GRANT|REVOKE"))
2857 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
2858 * privileges (can't grant roles)
2860 if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
2861 COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
2862 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
2863 "EXECUTE", "USAGE", "ALL");
2865 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2866 " UNION SELECT 'SELECT'"
2867 " UNION SELECT 'INSERT'"
2868 " UNION SELECT 'UPDATE'"
2869 " UNION SELECT 'DELETE'"
2870 " UNION SELECT 'TRUNCATE'"
2871 " UNION SELECT 'REFERENCES'"
2872 " UNION SELECT 'TRIGGER'"
2873 " UNION SELECT 'CREATE'"
2874 " UNION SELECT 'CONNECT'"
2875 " UNION SELECT 'TEMPORARY'"
2876 " UNION SELECT 'EXECUTE'"
2877 " UNION SELECT 'USAGE'"
2878 " UNION SELECT 'ALL'");
2882 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2885 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2887 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2888 COMPLETE_WITH_CONST("ON");
2889 else if (TailMatches2("GRANT", MatchAny))
2890 COMPLETE_WITH_CONST("TO");
2892 COMPLETE_WITH_CONST("FROM");
2896 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2899 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2900 * result via UNION; seems to work intuitively.
2902 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2903 * here will only work if the privilege list contains exactly one
2906 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2909 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
2910 * objects supported.
2912 if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
2913 COMPLETE_WITH_LIST5("TABLES", "SEQUENCES", "FUNCTIONS", "TYPES", "SCHEMAS");
2915 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2916 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2917 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2918 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2919 " UNION SELECT 'DATABASE'"
2920 " UNION SELECT 'DOMAIN'"
2921 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2922 " UNION SELECT 'FOREIGN SERVER'"
2923 " UNION SELECT 'FUNCTION'"
2924 " UNION SELECT 'LANGUAGE'"
2925 " UNION SELECT 'LARGE OBJECT'"
2926 " UNION SELECT 'SCHEMA'"
2927 " UNION SELECT 'SEQUENCE'"
2928 " UNION SELECT 'TABLE'"
2929 " UNION SELECT 'TABLESPACE'"
2930 " UNION SELECT 'TYPE'");
2932 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2933 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2934 "TABLES IN SCHEMA");
2935 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2936 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2939 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2940 * appropriate objects.
2942 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2944 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2946 if (TailMatches1("DATABASE"))
2947 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2948 else if (TailMatches1("DOMAIN"))
2949 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2950 else if (TailMatches1("FUNCTION"))
2951 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2952 else if (TailMatches1("LANGUAGE"))
2953 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2954 else if (TailMatches1("SCHEMA"))
2955 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2956 else if (TailMatches1("SEQUENCE"))
2957 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2958 else if (TailMatches1("TABLE"))
2959 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2960 else if (TailMatches1("TABLESPACE"))
2961 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2962 else if (TailMatches1("TYPE"))
2963 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2964 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2965 COMPLETE_WITH_CONST("TO");
2967 COMPLETE_WITH_CONST("FROM");
2971 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2972 * CURRENT_USER, or SESSION_USER.
2974 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2975 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2976 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2977 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
2978 else if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
2979 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2980 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2981 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2982 COMPLETE_WITH_CONST("TO");
2983 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2984 COMPLETE_WITH_CONST("FROM");
2986 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2987 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2989 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2990 COMPLETE_WITH_CONST("TO");
2992 COMPLETE_WITH_CONST("FROM");
2995 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2996 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2998 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2999 COMPLETE_WITH_CONST("TO");
3001 COMPLETE_WITH_CONST("FROM");
3004 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
3005 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
3007 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3008 COMPLETE_WITH_CONST("TO");
3010 COMPLETE_WITH_CONST("FROM");
3014 else if (TailMatches3("FROM", MatchAny, "GROUP"))
3015 COMPLETE_WITH_CONST("BY");
3017 /* IMPORT FOREIGN SCHEMA */
3018 else if (Matches1("IMPORT"))
3019 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
3020 else if (Matches2("IMPORT", "FOREIGN"))
3021 COMPLETE_WITH_CONST("SCHEMA");
3023 /* INSERT --- can be inside EXPLAIN, RULE, etc */
3024 /* Complete INSERT with "INTO" */
3025 else if (TailMatches1("INSERT"))
3026 COMPLETE_WITH_CONST("INTO");
3027 /* Complete INSERT INTO with table names */
3028 else if (TailMatches2("INSERT", "INTO"))
3029 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3030 /* Complete "INSERT INTO <table> (" with attribute names */
3031 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
3032 COMPLETE_WITH_ATTR(prev2_wd, "");
3035 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
3036 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
3038 else if (TailMatches3("INSERT", "INTO", MatchAny))
3039 COMPLETE_WITH_LIST6("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
3042 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
3043 * "TABLE" or "OVERRIDING"
3045 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
3046 ends_with(prev_wd, ')'))
3047 COMPLETE_WITH_LIST4("SELECT", "TABLE", "VALUES", "OVERRIDING");
3049 /* Complete OVERRIDING */
3050 else if (TailMatches1("OVERRIDING"))
3051 COMPLETE_WITH_LIST2("SYSTEM VALUE", "USER VALUE");
3053 /* Complete after OVERRIDING clause */
3054 else if (TailMatches3("OVERRIDING", MatchAny, "VALUE"))
3055 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
3057 /* Insert an open parenthesis after "VALUES" */
3058 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
3059 COMPLETE_WITH_CONST("(");
3062 /* Complete LOCK [TABLE] with a list of tables */
3063 else if (Matches1("LOCK"))
3064 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
3065 " UNION SELECT 'TABLE'");
3066 else if (Matches2("LOCK", "TABLE"))
3067 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
3069 /* For the following, handle the case of a single table only for now */
3071 /* Complete LOCK [TABLE] <table> with "IN" */
3072 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
3073 Matches3("LOCK", "TABLE", MatchAny))
3074 COMPLETE_WITH_CONST("IN");
3076 /* Complete LOCK [TABLE] <table> IN with a lock mode */
3077 else if (Matches3("LOCK", MatchAny, "IN") ||
3078 Matches4("LOCK", "TABLE", MatchAny, "IN"))
3079 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
3080 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
3081 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
3082 "SHARE ROW EXCLUSIVE MODE",
3083 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
3085 /* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
3086 else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
3087 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
3088 COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
3090 /* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
3091 else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
3092 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
3093 COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
3094 "UPDATE EXCLUSIVE MODE");
3096 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
3097 else if (TailMatches1("NOTIFY"))
3098 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'");
3101 else if (TailMatches1("OPTIONS"))
3102 COMPLETE_WITH_CONST("(");
3104 /* OWNER TO - complete with available roles */
3105 else if (TailMatches2("OWNER", "TO"))
3106 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3109 else if (TailMatches3("FROM", MatchAny, "ORDER"))
3110 COMPLETE_WITH_CONST("BY");
3111 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
3112 COMPLETE_WITH_ATTR(prev3_wd, "");
3115 else if (Matches3("PREPARE", MatchAny, "AS"))
3116 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
3119 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
3120 * managers, not for manual use in interactive sessions.
3123 /* REASSIGN OWNED BY xxx TO yyy */
3124 else if (Matches1("REASSIGN"))
3125 COMPLETE_WITH_CONST("OWNED BY");
3126 else if (Matches2("REASSIGN", "OWNED"))
3127 COMPLETE_WITH_CONST("BY");
3128 else if (Matches3("REASSIGN", "OWNED", "BY"))
3129 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3130 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
3131 COMPLETE_WITH_CONST("TO");
3132 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
3133 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3135 /* REFRESH MATERIALIZED VIEW */
3136 else if (Matches1("REFRESH"))
3137 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
3138 else if (Matches2("REFRESH", "MATERIALIZED"))
3139 COMPLETE_WITH_CONST("VIEW");
3140 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
3141 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
3142 " UNION SELECT 'CONCURRENTLY'");
3143 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
3144 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3145 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
3146 COMPLETE_WITH_CONST("WITH");
3147 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
3148 COMPLETE_WITH_CONST("WITH");
3149 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
3150 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3151 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
3152 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3153 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
3154 COMPLETE_WITH_CONST("DATA");
3155 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
3156 COMPLETE_WITH_CONST("DATA");
3159 else if (Matches1("REINDEX"))
3160 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
3161 else if (Matches2("REINDEX", "TABLE"))
3162 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3163 else if (Matches2("REINDEX", "INDEX"))
3164 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3165 else if (Matches2("REINDEX", "SCHEMA"))
3166 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3167 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
3168 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3170 /* SECURITY LABEL */
3171 else if (Matches1("SECURITY"))
3172 COMPLETE_WITH_CONST("LABEL");
3173 else if (Matches2("SECURITY", "LABEL"))
3174 COMPLETE_WITH_LIST2("ON", "FOR");
3175 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
3176 COMPLETE_WITH_CONST("ON");
3177 else if (Matches3("SECURITY", "LABEL", "ON") ||
3178 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
3180 static const char *const list_SECURITY_LABEL[] =
3181 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
3182 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
3183 "MATERIALIZED VIEW", "LANGUAGE", "PUBLICATION", "ROLE", "SCHEMA",
3184 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW", NULL};
3186 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
3188 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
3189 COMPLETE_WITH_CONST("IS");
3194 /* SET, RESET, SHOW */
3195 /* Complete with a variable name */
3196 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
3197 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
3198 else if (Matches1("SHOW"))
3199 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
3200 /* Complete "SET TRANSACTION" */
3201 else if (Matches2("SET", "TRANSACTION"))
3202 COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3203 else if (Matches2("BEGIN|START", "TRANSACTION") ||
3204 Matches2("BEGIN", "WORK") ||
3205 Matches1("BEGIN") ||
3206 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
3207 COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3208 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
3209 Matches2("BEGIN", "NOT") ||
3210 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
3211 COMPLETE_WITH_CONST("DEFERRABLE");
3212 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
3213 Matches2("BEGIN", "ISOLATION") ||
3214 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
3215 COMPLETE_WITH_CONST("LEVEL");
3216 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
3217 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
3218 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
3219 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
3220 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
3221 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
3222 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
3223 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
3224 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
3225 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
3226 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
3227 COMPLETE_WITH_CONST("READ");
3228 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
3229 Matches2("BEGIN", "READ") ||
3230 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
3231 COMPLETE_WITH_LIST2("ONLY", "WRITE");
3232 /* SET CONSTRAINTS */
3233 else if (Matches2("SET", "CONSTRAINTS"))
3234 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
3235 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
3236 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
3237 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
3238 /* Complete SET ROLE */
3239 else if (Matches2("SET", "ROLE"))
3240 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3241 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
3242 else if (Matches2("SET", "SESSION"))
3243 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
3244 /* Complete SET SESSION AUTHORIZATION with username */
3245 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
3246 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
3247 /* Complete RESET SESSION with AUTHORIZATION */
3248 else if (Matches2("RESET", "SESSION"))
3249 COMPLETE_WITH_CONST("AUTHORIZATION");
3250 /* Complete SET <var> with "TO" */
3251 else if (Matches2("SET", MatchAny))
3252 COMPLETE_WITH_CONST("TO");
3253 /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
3254 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
3255 TailMatches2("SET", MatchAny))
3256 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
3257 /* Suggest possible variable values */
3258 else if (TailMatches3("SET", MatchAny, "TO|="))
3260 /* special cased code for individual GUCs */
3261 if (TailMatches2("DateStyle", "TO|="))
3263 static const char *const my_list[] =
3264 {"ISO", "SQL", "Postgres", "German",
3265 "YMD", "DMY", "MDY",
3266 "US", "European", "NonEuropean",
3269 COMPLETE_WITH_LIST(my_list);
3271 else if (TailMatches2("search_path", "TO|="))
3272 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
3273 " AND nspname not like 'pg\\_toast%%' "
3274 " AND nspname not like 'pg\\_temp%%' "
3275 " UNION SELECT 'DEFAULT' ");
3278 /* generic, type based, GUC support */
3279 char *guctype = get_guctype(prev2_wd);
3281 if (guctype && strcmp(guctype, "enum") == 0)
3283 char querybuf[1024];
3285 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
3286 COMPLETE_WITH_QUERY(querybuf);
3288 else if (guctype && strcmp(guctype, "bool") == 0)
3289 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
3290 "1", "0", "DEFAULT");
3292 COMPLETE_WITH_CONST("DEFAULT");
3299 /* START TRANSACTION */
3300 else if (Matches1("START"))
3301 COMPLETE_WITH_CONST("TRANSACTION");
3303 /* TABLE, but not TABLE embedded in other commands */
3304 else if (Matches1("TABLE"))
3305 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3308 else if (TailMatches1("TABLESAMPLE"))
3309 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
3310 else if (TailMatches2("TABLESAMPLE", MatchAny))
3311 COMPLETE_WITH_CONST("(");
3314 else if (Matches1("TRUNCATE"))
3315 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3318 else if (Matches1("UNLISTEN"))
3319 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 '*'");
3321 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
3322 /* If prev. word is UPDATE suggest a list of tables */
3323 else if (TailMatches1("UPDATE"))
3324 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3325 /* Complete UPDATE <table> with "SET" */
3326 else if (TailMatches2("UPDATE", MatchAny))
3327 COMPLETE_WITH_CONST("SET");
3328 /* Complete UPDATE <table> SET with list of attributes */
3329 else if (TailMatches3("UPDATE", MatchAny, "SET"))
3330 COMPLETE_WITH_ATTR(prev2_wd, "");
3331 /* UPDATE <table> SET <attr> = */
3332 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
3333 COMPLETE_WITH_CONST("=");
3336 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
3337 COMPLETE_WITH_CONST("FOR");
3338 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
3339 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3340 " UNION SELECT 'CURRENT_USER'"
3341 " UNION SELECT 'PUBLIC'"
3342 " UNION SELECT 'USER'");
3343 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
3344 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3345 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
3346 COMPLETE_WITH_CONST("SERVER");
3347 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
3348 COMPLETE_WITH_CONST("OPTIONS");
3351 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
3352 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
3354 else if (Matches1("VACUUM"))
3355 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3356 " UNION SELECT 'FULL'"
3357 " UNION SELECT 'FREEZE'"
3358 " UNION SELECT 'ANALYZE'"
3359 " UNION SELECT 'VERBOSE'");
3360 else if (Matches2("VACUUM", "FULL|FREEZE"))
3361 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3362 " UNION SELECT 'ANALYZE'"
3363 " UNION SELECT 'VERBOSE'");
3364 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
3365 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3366 " UNION SELECT 'VERBOSE'");
3367 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
3368 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3369 " UNION SELECT 'ANALYZE'");
3370 else if (Matches2("VACUUM", "VERBOSE"))
3371 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3372 " UNION SELECT 'ANALYZE'");
3373 else if (Matches2("VACUUM", "ANALYZE"))
3374 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3375 " UNION SELECT 'VERBOSE'");
3376 else if (HeadMatches1("VACUUM"))
3377 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3379 /* WITH [RECURSIVE] */
3382 * Only match when WITH is the first word, as WITH may appear in many
3385 else if (Matches1("WITH"))
3386 COMPLETE_WITH_CONST("RECURSIVE");
3389 /* Complete with list of tables */
3390 else if (Matches1("ANALYZE"))
3391 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
3394 /* Simple case of the word before the where being the table name */
3395 else if (TailMatches2(MatchAny, "WHERE"))
3396 COMPLETE_WITH_ATTR(prev2_wd, "");
3399 /* TODO: also include SRF ? */
3400 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
3401 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3404 else if (TailMatches1("JOIN"))
3405 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3407 /* Backslash commands */
3408 /* TODO: \dc \dd \dl */
3409 else if (TailMatchesCS1("\\?"))
3410 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
3411 else if (TailMatchesCS1("\\connect|\\c"))
3413 if (!recognized_connection_string(text))
3414 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3416 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
3418 if (!recognized_connection_string(prev_wd))
3419 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3421 else if (TailMatchesCS1("\\da*"))
3422 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
3423 else if (TailMatchesCS1("\\dA*"))
3424 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3425 else if (TailMatchesCS1("\\db*"))
3426 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3427 else if (TailMatchesCS1("\\dD*"))
3428 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3429 else if (TailMatchesCS1("\\des*"))
3430 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3431 else if (TailMatchesCS1("\\deu*"))
3432 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3433 else if (TailMatchesCS1("\\dew*"))
3434 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3435 else if (TailMatchesCS1("\\df*"))
3436 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3438 else if (TailMatchesCS1("\\dFd*"))
3439 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
3440 else if (TailMatchesCS1("\\dFp*"))
3441 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
3442 else if (TailMatchesCS1("\\dFt*"))
3443 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
3444 /* must be at end of \dF alternatives: */
3445 else if (TailMatchesCS1("\\dF*"))
3446 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
3448 else if (TailMatchesCS1("\\di*"))
3449 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3450 else if (TailMatchesCS1("\\dL*"))
3451 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3452 else if (TailMatchesCS1("\\dn*"))
3453 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3454 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
3455 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3456 else if (TailMatchesCS1("\\ds*"))
3457 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3458 else if (TailMatchesCS1("\\dt*"))
3459 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3460 else if (TailMatchesCS1("\\dT*"))
3461 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3462 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
3463 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3464 else if (TailMatchesCS1("\\dv*"))
3465 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3466 else if (TailMatchesCS1("\\dx*"))
3467 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
3468 else if (TailMatchesCS1("\\dm*"))
3469 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3470 else if (TailMatchesCS1("\\dE*"))
3471 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3472 else if (TailMatchesCS1("\\dy*"))
3473 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3475 /* must be at end of \d alternatives: */
3476 else if (TailMatchesCS1("\\d*"))
3477 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3479 else if (TailMatchesCS1("\\ef"))
3480 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3481 else if (TailMatchesCS1("\\ev"))
3482 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3484 else if (TailMatchesCS1("\\encoding"))
3485 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3486 else if (TailMatchesCS1("\\h|\\help"))
3487 COMPLETE_WITH_LIST(sql_commands);
3488 else if (TailMatchesCS2("\\h|\\help", MatchAny))
3490 if (TailMatches1("DROP"))
3491 matches = completion_matches(text, drop_command_generator);
3492 else if (TailMatches1("ALTER"))
3493 matches = completion_matches(text, alter_command_generator);
3496 * CREATE is recognized by tail match elsewhere, so doesn't need to be
3500 else if (TailMatchesCS3("\\h|\\help", MatchAny, MatchAny))
3502 if (TailMatches2("CREATE|DROP", "ACCESS"))
3503 COMPLETE_WITH_CONST("METHOD");
3504 else if (TailMatches2("ALTER", "DEFAULT"))
3505 COMPLETE_WITH_CONST("PRIVILEGES");
3506 else if (TailMatches2("CREATE|ALTER|DROP", "EVENT"))
3507 COMPLETE_WITH_CONST("TRIGGER");
3508 else if (TailMatches2("CREATE|ALTER|DROP", "FOREIGN"))
3509 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
3510 else if (TailMatches2("ALTER", "LARGE"))
3511 COMPLETE_WITH_CONST("OBJECT");
3512 else if (TailMatches2("CREATE|ALTER|DROP", "MATERIALIZED"))
3513 COMPLETE_WITH_CONST("VIEW");
3514 else if (TailMatches2("CREATE|ALTER|DROP", "TEXT"))
3515 COMPLETE_WITH_CONST("SEARCH");
3516 else if (TailMatches2("CREATE|ALTER|DROP", "USER"))
3517 COMPLETE_WITH_CONST("MAPPING FOR");
3519 else if (TailMatchesCS4("\\h|\\help", MatchAny, MatchAny, MatchAny))
3521 if (TailMatches3("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
3522 COMPLETE_WITH_CONST("WRAPPER");
3523 else if (TailMatches3("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
3524 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3525 else if (TailMatches3("CREATE|ALTER|DROP", "USER", "MAPPING"))
3526 COMPLETE_WITH_CONST("FOR");
3528 else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
3529 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3530 else if (TailMatchesCS1("\\password"))
3531 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3532 else if (TailMatchesCS1("\\pset"))
3534 static const char *const my_list[] =
3535 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3536 "footer", "format", "linestyle", "null", "numericlocale",
3537 "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3538 "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3539 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3541 COMPLETE_WITH_LIST_CS(my_list);
3543 else if (TailMatchesCS2("\\pset", MatchAny))
3545 if (TailMatchesCS1("format"))
3547 static const char *const my_list[] =
3548 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3549 "latex", "latex-longtable", "troff-ms", NULL};
3551 COMPLETE_WITH_LIST_CS(my_list);
3553 else if (TailMatchesCS1("linestyle"))
3554 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3555 else if (TailMatchesCS1("unicode_border_linestyle|"
3556 "unicode_column_linestyle|"
3557 "unicode_header_linestyle"))
3558 COMPLETE_WITH_LIST_CS2("single", "double");
3560 else if (TailMatchesCS1("\\unset"))
3562 matches = complete_from_variables(text, "", "", true);
3564 else if (TailMatchesCS1("\\set"))
3566 matches = complete_from_variables(text, "", "", false);
3568 else if (TailMatchesCS2("\\set", MatchAny))
3570 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3571 "SINGLELINE|SINGLESTEP"))
3572 COMPLETE_WITH_LIST_CS2("on", "off");
3573 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3574 COMPLETE_WITH_LIST_CS4("lower", "upper",
3575 "preserve-lower", "preserve-upper");
3576 else if (TailMatchesCS1("ECHO"))
3577 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3578 else if (TailMatchesCS1("ECHO_HIDDEN"))
3579 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3580 else if (TailMatchesCS1("HISTCONTROL"))
3581 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3582 "ignoreboth", "none");
3583 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3584 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3585 else if (TailMatchesCS1("SHOW_CONTEXT"))
3586 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3587 else if (TailMatchesCS1("VERBOSITY"))
3588 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3590 else if (TailMatchesCS1("\\sf*"))
3591 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3592 else if (TailMatchesCS1("\\sv*"))
3593 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3594 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3595 "\\ir|\\include_relative|\\o|\\out|"
3596 "\\s|\\w|\\write|\\lo_import"))
3598 completion_charp = "\\";
3599 matches = completion_matches(text, complete_from_files);
3603 * Finally, we look through the list of "things", such as TABLE, INDEX and
3604 * check if that was the previous word. If so, execute the query to get a
3611 for (i = 0; words_after_create[i].name; i++)
3613 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3615 if (words_after_create[i].query)
3616 COMPLETE_WITH_QUERY(words_after_create[i].query);
3617 else if (words_after_create[i].squery)
3618 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3626 * If we still don't have anything to match we have to fabricate some sort
3627 * of default list. If we were to just return NULL, readline automatically
3628 * attempts filename completion, and that's usually no good.
3630 if (matches == NULL)
3632 COMPLETE_WITH_CONST("");
3633 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3634 rl_completion_append_character = '\0';
3639 free(previous_words);
3642 /* Return our Grand List O' Matches */
3648 * GENERATOR FUNCTIONS
3650 * These functions do all the actual work of completing the input. They get
3651 * passed the text so far and the count how many times they have been called
3652 * so far with the same text.
3653 * If you read the above carefully, you'll see that these don't get called
3654 * directly but through the readline interface.
3655 * The return value is expected to be the full completion of the text, going
3656 * through a list each time, or NULL if there are no more matches. The string
3657 * will be free()'d by readline, so you must run it through strdup() or
3658 * something of that sort.
3662 * Common routine for create_command_generator and drop_command_generator.
3663 * Entries that have 'excluded' flags are not returned.
3666 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3668 static int list_index,
3672 /* If this is the first time for this completion, init some values */
3676 string_length = strlen(text);
3679 /* find something that matches */
3680 while ((name = words_after_create[list_index++].name))
3682 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3683 !(words_after_create[list_index - 1].flags & excluded))
3684 return pg_strdup_keyword_case(name, text);
3686 /* if nothing matches, return NULL */
3691 * This one gives you one from a list of things you can put after CREATE
3695 create_command_generator(const char *text, int state)
3697 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3701 * This function gives you a list of things you can put after a DROP command.
3704 drop_command_generator(const char *text, int state)
3706 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3710 * This function gives you a list of things you can put after an ALTER command.
3713 alter_command_generator(const char *text, int state)
3715 return create_or_drop_command_generator(text, state, THING_NO_ALTER);
3718 /* The following two functions are wrappers for _complete_from_query */
3721 complete_from_query(const char *text, int state)
3723 return _complete_from_query(0, text, state);
3727 complete_from_schema_query(const char *text, int state)
3729 return _complete_from_query(1, text, state);
3734 * This creates a list of matching things, according to a query pointed to
3735 * by completion_charp.
3736 * The query can be one of two kinds:
3738 * 1. A simple query which must contain a %d and a %s, which will be replaced
3739 * by the string length of the text and the text itself. The query may also
3740 * have up to four more %s in it; the first two such will be replaced by the
3741 * value of completion_info_charp, the next two by the value of
3742 * completion_info_charp2.
3744 * 2. A schema query used for completion of both schema and relation names.
3745 * These are more complex and must contain in the following order:
3746 * %d %s %d %s %d %s %s %d %s
3747 * where %d is the string length of the text and %s the text itself.
3749 * It is assumed that strings should be escaped to become SQL literals
3750 * (that is, what is in the query is actually ... '%s' ...)
3752 * See top of file for examples of both kinds of query.
3755 _complete_from_query(int is_schema_query, const char *text, int state)
3757 static int list_index,
3759 static PGresult *result = NULL;
3762 * If this is the first time for this completion, we fetch a list of our
3763 * "things" from the backend.
3767 PQExpBufferData query_buffer;
3770 char *e_info_charp2;
3771 const char *pstr = text;
3772 int char_length = 0;
3775 byte_length = strlen(text);
3778 * Count length as number of characters (not bytes), for passing to
3784 pstr += PQmblen(pstr, pset.encoding);
3787 /* Free any prior result */
3791 /* Set up suitably-escaped copies of textual inputs */
3792 e_text = escape_string(text);
3794 if (completion_info_charp)
3795 e_info_charp = escape_string(completion_info_charp);
3797 e_info_charp = NULL;
3799 if (completion_info_charp2)
3800 e_info_charp2 = escape_string(completion_info_charp2);
3802 e_info_charp2 = NULL;
3804 initPQExpBuffer(&query_buffer);
3806 if (is_schema_query)
3808 /* completion_squery gives us the pieces to assemble */
3809 const char *qualresult = completion_squery->qualresult;
3811 if (qualresult == NULL)
3812 qualresult = completion_squery->result;
3814 /* Get unqualified names matching the input-so-far */
3815 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3816 completion_squery->result,
3817 completion_squery->catname);
3818 if (completion_squery->selcondition)
3819 appendPQExpBuffer(&query_buffer, "%s AND ",
3820 completion_squery->selcondition);
3821 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3822 completion_squery->result,
3823 char_length, e_text);
3824 appendPQExpBuffer(&query_buffer, " AND %s",
3825 completion_squery->viscondition);
3828 * When fetching relation names, suppress system catalogs unless
3829 * the input-so-far begins with "pg_". This is a compromise
3830 * between not offering system catalogs for completion at all, and
3831 * having them swamp the result when the input is just "p".
3833 if (strcmp(completion_squery->catname,
3834 "pg_catalog.pg_class c") == 0 &&
3835 strncmp(text, "pg_", 3) !=0)
3837 appendPQExpBufferStr(&query_buffer,
3838 " AND c.relnamespace <> (SELECT oid FROM"
3839 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3843 * Add in matching schema names, but only if there is more than
3844 * one potential match among schema names.
3846 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3847 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3848 "FROM pg_catalog.pg_namespace n "
3849 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3850 char_length, e_text);
3851 appendPQExpBuffer(&query_buffer,
3852 " AND (SELECT pg_catalog.count(*)"
3853 " FROM pg_catalog.pg_namespace"
3854 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3855 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3856 char_length, e_text);
3859 * Add in matching qualified names, but only if there is exactly
3860 * one schema matching the input-so-far.
3862 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3863 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3864 "FROM %s, pg_catalog.pg_namespace n "
3865 "WHERE %s = n.oid AND ",
3867 completion_squery->catname,
3868 completion_squery->namespace);
3869 if (completion_squery->selcondition)
3870 appendPQExpBuffer(&query_buffer, "%s AND ",
3871 completion_squery->selcondition);
3872 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3874 char_length, e_text);
3877 * This condition exploits the single-matching-schema rule to
3878 * speed up the query
3880 appendPQExpBuffer(&query_buffer,
3881 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3882 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3883 char_length, e_text);
3884 appendPQExpBuffer(&query_buffer,
3885 " AND (SELECT pg_catalog.count(*)"
3886 " FROM pg_catalog.pg_namespace"
3887 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3888 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3889 char_length, e_text);
3891 /* If an addon query was provided, use it */
3892 if (completion_charp)
3893 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3897 /* completion_charp is an sprintf-style format string */
3898 appendPQExpBuffer(&query_buffer, completion_charp,
3899 char_length, e_text,
3900 e_info_charp, e_info_charp,
3901 e_info_charp2, e_info_charp2);
3904 /* Limit the number of records in the result */
3905 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3906 completion_max_records);
3908 result = exec_query(query_buffer.data);
3910 termPQExpBuffer(&query_buffer);
3915 free(e_info_charp2);
3918 /* Find something that matches */
3919 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3923 while (list_index < PQntuples(result) &&
3924 (item = PQgetvalue(result, list_index++, 0)))
3925 if (pg_strncasecmp(text, item, byte_length) == 0)
3926 return pg_strdup(item);
3929 /* If nothing matches, free the db structure and return null */
3937 * This function returns in order one of a fixed, NULL pointer terminated list
3938 * of strings (if matching). This can be used if there are only a fixed number
3939 * SQL words that can appear at certain spot.
3942 complete_from_list(const char *text, int state)
3944 static int string_length,
3947 static bool casesensitive;
3950 /* need to have a list */
3951 Assert(completion_charpp != NULL);
3953 /* Initialization */
3957 string_length = strlen(text);
3958 casesensitive = completion_case_sensitive;
3962 while ((item = completion_charpp[list_index++]))
3964 /* First pass is case sensitive */
3965 if (casesensitive && strncmp(text, item, string_length) == 0)
3968 return pg_strdup(item);
3971 /* Second pass is case insensitive, don't bother counting matches */
3972 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3974 if (completion_case_sensitive)
3975 return pg_strdup(item);
3979 * If case insensitive matching was requested initially,
3980 * adjust the case according to setting.
3982 return pg_strdup_keyword_case(item, text);
3987 * No matches found. If we're not case insensitive already, lets switch to
3988 * being case insensitive and try again
3990 if (casesensitive && matches == 0)
3992 casesensitive = false;
3995 return complete_from_list(text, state);
3998 /* If no more matches, return null. */
4004 * This function returns one fixed string the first time even if it doesn't
4005 * match what's there, and nothing the second time. This should be used if
4006 * there is only one possibility that can appear at a certain spot, so
4007 * misspellings will be overwritten. The string to be passed must be in
4011 complete_from_const(const char *text, int state)
4013 Assert(completion_charp != NULL);
4016 if (completion_case_sensitive)
4017 return pg_strdup(completion_charp);
4021 * If case insensitive matching was requested initially, adjust
4022 * the case according to setting.
4024 return pg_strdup_keyword_case(completion_charp, text);
4032 * This function appends the variable name with prefix and suffix to
4033 * the variable names array.
4036 append_variable_names(char ***varnames, int *nvars,
4037 int *maxvars, const char *varname,
4038 const char *prefix, const char *suffix)
4040 if (*nvars >= *maxvars)
4043 *varnames = (char **) pg_realloc(*varnames,
4044 ((*maxvars) + 1) * sizeof(char *));
4047 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
4052 * This function supports completion with the name of a psql variable.
4053 * The variable names can be prefixed and suffixed with additional text
4054 * to support quoting usages. If need_value is true, only variables
4055 * that are currently set are included; otherwise, special variables
4056 * (those that have hooks) are included even if currently unset.
4059 complete_from_variables(const char *text, const char *prefix, const char *suffix,
4067 struct _variable *ptr;
4069 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
4071 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
4073 if (need_value && !(ptr->value))
4075 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
4079 varnames[nvars] = NULL;
4080 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
4082 for (i = 0; i < nvars; i++)
4091 * This function wraps rl_filename_completion_function() to strip quotes from
4092 * the input before searching for matches and to quote any matches for which
4093 * the consuming command will require it.
4096 complete_from_files(const char *text, int state)
4098 static const char *unquoted_text;
4099 char *unquoted_match;
4104 /* Initialization: stash the unquoted input. */
4105 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
4106 false, true, pset.encoding);
4107 /* expect a NULL return for the empty string only */
4110 Assert(*text == '\0');
4111 unquoted_text = text;
4115 unquoted_match = filename_completion_function(unquoted_text, state);
4119 * Caller sets completion_charp to a zero- or one-character string
4120 * containing the escape character. This is necessary since \copy has
4121 * no escape character, but every other backslash command recognizes
4122 * "\" as an escape character. Since we have only two callers, don't
4123 * bother providing a macro to simplify this.
4125 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
4126 '\'', *completion_charp, pset.encoding);
4128 free(unquoted_match);
4130 ret = unquoted_match;
4137 /* HELPER FUNCTIONS */
4141 * Make a pg_strdup copy of s and convert the case according to
4142 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
4145 pg_strdup_keyword_case(const char *s, const char *ref)
4149 unsigned char first = ref[0];
4153 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
4154 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
4155 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
4156 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
4158 for (p = ret; *p; p++)
4159 *p = pg_tolower((unsigned char) *p);
4163 for (p = ret; *p; p++)
4164 *p = pg_toupper((unsigned char) *p);
4172 * escape_string - Escape argument for use as string literal.
4174 * The returned value has to be freed.
4177 escape_string(const char *text)
4182 text_length = strlen(text);
4184 result = pg_malloc(text_length * 2 + 1);
4185 PQescapeStringConn(pset.db, result, text, text_length, NULL);
4192 * Execute a query and report any errors. This should be the preferred way of
4193 * talking to the database in this file.
4196 exec_query(const char *query)
4200 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
4203 result = PQexec(pset.db, query);
4205 if (PQresultStatus(result) != PGRES_TUPLES_OK)
4208 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
4209 PQerrorMessage(pset.db), query);
4220 * Parse all the word(s) before point.
4222 * Returns a malloc'd array of character pointers that point into the malloc'd
4223 * data array returned to *buffer; caller must free() both of these when done.
4224 * *nwords receives the number of words found, ie, the valid length of the
4227 * Words are returned right to left, that is, previous_words[0] gets the last
4228 * word before point, previous_words[1] the next-to-last, etc.
4231 get_previous_words(int point, char **buffer, int *nwords)
4233 char **previous_words;
4236 int words_found = 0;
4240 * If we have anything in tab_completion_query_buf, paste it together with
4241 * rl_line_buffer to construct the full query. Otherwise we can just use
4242 * rl_line_buffer as the input string.
4244 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
4246 i = tab_completion_query_buf->len;
4247 buf = pg_malloc(point + i + 2);
4248 memcpy(buf, tab_completion_query_buf->data, i);
4250 memcpy(buf + i, rl_line_buffer, point);
4253 /* Readjust point to reference appropriate offset in buf */
4257 buf = rl_line_buffer;
4260 * Allocate an array of string pointers and a buffer to hold the strings
4261 * themselves. The worst case is that the line contains only
4262 * non-whitespace WORD_BREAKS characters, making each one a separate word.
4263 * This is usually much more space than we need, but it's cheaper than
4264 * doing a separate malloc() for each word.
4266 previous_words = (char **) pg_malloc(point * sizeof(char *));
4267 *buffer = outptr = (char *) pg_malloc(point * 2);
4270 * First we look for a non-word char before the current point. (This is
4271 * probably useless, if readline is on the same page as we are about what
4272 * is a word, but if so it's cheap.)
4274 for (i = point - 1; i >= 0; i--)
4276 if (strchr(WORD_BREAKS, buf[i]))
4282 * Now parse words, working backwards, until we hit start of line. The
4283 * backwards scan has some interesting but intentional properties
4284 * concerning parenthesis handling.
4290 bool inquotes = false;
4291 int parentheses = 0;
4293 /* now find the first non-space which then constitutes the end */
4295 for (i = point; i >= 0; i--)
4297 if (!isspace((unsigned char) buf[i]))
4303 /* if no end found, we're done */
4308 * Otherwise we now look for the start. The start is either the last
4309 * character before any word-break character going backwards from the
4310 * end, or it's simply character 0. We also handle open quotes and
4313 for (start = end; start > 0; start--)
4315 if (buf[start] == '"')
4316 inquotes = !inquotes;
4319 if (buf[start] == ')')
4321 else if (buf[start] == '(')
4323 if (--parentheses <= 0)
4326 else if (parentheses == 0 &&
4327 strchr(WORD_BREAKS, buf[start - 1]))
4332 /* Return the word located at start to end inclusive */
4333 previous_words[words_found++] = outptr;
4334 i = end - start + 1;
4335 memcpy(outptr, &buf[start], i);
4339 /* Continue searching */
4343 /* Release parsing input workspace, if we made one above */
4344 if (buf != rl_line_buffer)
4347 *nwords = words_found;
4348 return previous_words;
4352 * Look up the type for the GUC variable with the passed name.
4354 * Returns NULL if the variable is unknown. Otherwise the returned string,
4355 * containing the type, has to be freed.
4358 get_guctype(const char *varname)
4360 PQExpBufferData query_buffer;
4363 char *guctype = NULL;
4365 e_varname = escape_string(varname);
4367 initPQExpBuffer(&query_buffer);
4368 appendPQExpBuffer(&query_buffer,
4369 "SELECT vartype FROM pg_catalog.pg_settings "
4370 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
4373 result = exec_query(query_buffer.data);
4374 termPQExpBuffer(&query_buffer);
4377 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
4378 guctype = pg_strdup(PQgetvalue(result, 0, 0));
4388 * Surround a string with single quotes. This works for both SQL and
4389 * psql internal. Currently disabled because it is reported not to
4390 * cooperate with certain versions of readline.
4393 quote_file_name(char *text, int match_type, char *quote_pointer)
4398 (void) quote_pointer; /* not used */
4400 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
4401 s = pg_malloc(length);
4403 strcpy(s + 1, text);
4404 if (match_type == SINGLE_MATCH)
4405 s[length - 2] = '\'';
4406 s[length - 1] = '\0';
4411 dequote_file_name(char *text, char quote_char)
4417 return pg_strdup(text);
4419 length = strlen(text);
4420 s = pg_malloc(length - 2 + 1);
4421 strlcpy(s, text +1, length - 2 + 1);
4425 #endif /* NOT_USED */
4427 #endif /* USE_READLINE */