2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2018, PostgreSQL Global Development Group
6 * src/bin/psql/tab-complete.c
9 /*----------------------------------------------------------------------
10 * This file implements a somewhat more sophisticated readline "TAB
11 * completion" in psql. It is not intended to be AI, to replace
12 * learning SQL, or to relieve you from thinking about what you're
13 * doing. Also it does not always give you all the syntactically legal
14 * completions, only those that are the most common or the ones that
15 * the programmer felt most like implementing.
17 * CAVEAT: Tab completion causes queries to be sent to the backend.
18 * The number of tuples returned gets limited, in most default
19 * installations to 1000, but if you still don't like this prospect,
20 * you can turn off tab completion in your ~/.inputrc (or else
21 * ${INPUTRC}) file so:
24 * set disable-completion on
27 * See `man 3 readline' or `info readline' for the full details.
30 * - Quotes, parentheses, and other funny characters are not handled
31 * all that gracefully.
32 *----------------------------------------------------------------------
35 #include "postgres_fe.h"
36 #include "tab-complete.h"
39 /* If we don't have this, we might as well forget about the whole thing: */
44 #include "catalog/pg_class.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_procedures = {
428 "pg_catalog.pg_proc p",
432 "pg_catalog.pg_function_is_visible(p.oid)",
436 "pg_catalog.quote_ident(p.proname)",
441 static const SchemaQuery Query_for_list_of_routines = {
443 "pg_catalog.pg_proc p",
447 "pg_catalog.pg_function_is_visible(p.oid)",
451 "pg_catalog.quote_ident(p.proname)",
456 static const SchemaQuery Query_for_list_of_sequences = {
458 "pg_catalog.pg_class c",
460 "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
462 "pg_catalog.pg_table_is_visible(c.oid)",
466 "pg_catalog.quote_ident(c.relname)",
471 static const SchemaQuery Query_for_list_of_foreign_tables = {
473 "pg_catalog.pg_class c",
475 "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
477 "pg_catalog.pg_table_is_visible(c.oid)",
481 "pg_catalog.quote_ident(c.relname)",
486 static const SchemaQuery Query_for_list_of_tables = {
488 "pg_catalog.pg_class c",
490 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
491 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
493 "pg_catalog.pg_table_is_visible(c.oid)",
497 "pg_catalog.quote_ident(c.relname)",
502 static const SchemaQuery Query_for_list_of_partitioned_tables = {
504 "pg_catalog.pg_class c",
506 "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
508 "pg_catalog.pg_table_is_visible(c.oid)",
512 "pg_catalog.quote_ident(c.relname)",
517 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
519 "pg_catalog.pg_constraint c",
523 "true", /* there is no pg_constraint_is_visible */
527 "pg_catalog.quote_ident(c.conname)",
532 /* Relations supporting INSERT, UPDATE or DELETE */
533 static const SchemaQuery Query_for_list_of_updatables = {
535 "pg_catalog.pg_class c",
537 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
538 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
539 CppAsString2(RELKIND_VIEW) ", "
540 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
542 "pg_catalog.pg_table_is_visible(c.oid)",
546 "pg_catalog.quote_ident(c.relname)",
551 static const SchemaQuery Query_for_list_of_relations = {
553 "pg_catalog.pg_class c",
557 "pg_catalog.pg_table_is_visible(c.oid)",
561 "pg_catalog.quote_ident(c.relname)",
566 static const SchemaQuery Query_for_list_of_tsvmf = {
568 "pg_catalog.pg_class c",
570 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
571 CppAsString2(RELKIND_SEQUENCE) ", "
572 CppAsString2(RELKIND_VIEW) ", "
573 CppAsString2(RELKIND_MATVIEW) ", "
574 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
575 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
577 "pg_catalog.pg_table_is_visible(c.oid)",
581 "pg_catalog.quote_ident(c.relname)",
586 static const SchemaQuery Query_for_list_of_tmf = {
588 "pg_catalog.pg_class c",
590 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
591 CppAsString2(RELKIND_MATVIEW) ", "
592 CppAsString2(RELKIND_FOREIGN_TABLE) ")",
594 "pg_catalog.pg_table_is_visible(c.oid)",
598 "pg_catalog.quote_ident(c.relname)",
603 static const SchemaQuery Query_for_list_of_tm = {
605 "pg_catalog.pg_class c",
607 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
608 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_views = {
621 "pg_catalog.pg_class c",
623 "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
625 "pg_catalog.pg_table_is_visible(c.oid)",
629 "pg_catalog.quote_ident(c.relname)",
634 static const SchemaQuery Query_for_list_of_matviews = {
636 "pg_catalog.pg_class c",
638 "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
640 "pg_catalog.pg_table_is_visible(c.oid)",
644 "pg_catalog.quote_ident(c.relname)",
649 static const SchemaQuery Query_for_list_of_statistics = {
651 "pg_catalog.pg_statistic_ext s",
655 "pg_catalog.pg_statistics_obj_is_visible(s.oid)",
659 "pg_catalog.quote_ident(s.stxname)",
666 * Queries to get lists of names of various kinds of things, possibly
667 * restricted to names matching a partially entered name. In these queries,
668 * the first %s will be replaced by the text entered so far (suitably escaped
669 * to become a SQL literal string). %d will be replaced by the length of the
670 * string (in unescaped form). A second and third %s, if present, will be
671 * replaced by a suitably-escaped version of the string provided in
672 * completion_info_charp. A fourth and fifth %s are similarly replaced by
673 * completion_info_charp2.
675 * Beware that the allowed sequences of %s and %d are determined by
676 * _complete_from_query().
679 #define Query_for_list_of_attributes \
680 "SELECT pg_catalog.quote_ident(attname) "\
681 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
682 " WHERE c.oid = a.attrelid "\
683 " AND a.attnum > 0 "\
684 " AND NOT a.attisdropped "\
685 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
686 " AND (pg_catalog.quote_ident(relname)='%s' "\
687 " OR '\"' || relname || '\"'='%s') "\
688 " AND pg_catalog.pg_table_is_visible(c.oid)"
690 #define Query_for_list_of_attributes_with_schema \
691 "SELECT pg_catalog.quote_ident(attname) "\
692 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
693 " WHERE c.oid = a.attrelid "\
694 " AND n.oid = c.relnamespace "\
695 " AND a.attnum > 0 "\
696 " AND NOT a.attisdropped "\
697 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
698 " AND (pg_catalog.quote_ident(relname)='%s' "\
699 " OR '\"' || relname || '\"' ='%s') "\
700 " AND (pg_catalog.quote_ident(nspname)='%s' "\
701 " OR '\"' || nspname || '\"' ='%s') "
703 #define Query_for_list_of_enum_values \
704 "SELECT pg_catalog.quote_literal(enumlabel) "\
705 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t "\
706 " WHERE t.oid = e.enumtypid "\
707 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
708 " AND (pg_catalog.quote_ident(typname)='%s' "\
709 " OR '\"' || typname || '\"'='%s') "\
710 " AND pg_catalog.pg_type_is_visible(t.oid)"
712 #define Query_for_list_of_enum_values_with_schema \
713 "SELECT pg_catalog.quote_literal(enumlabel) "\
714 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
715 " WHERE t.oid = e.enumtypid "\
716 " AND n.oid = t.typnamespace "\
717 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
718 " AND (pg_catalog.quote_ident(typname)='%s' "\
719 " OR '\"' || typname || '\"'='%s') "\
720 " AND (pg_catalog.quote_ident(nspname)='%s' "\
721 " OR '\"' || nspname || '\"' ='%s') "
723 #define Query_for_list_of_template_databases \
724 "SELECT pg_catalog.quote_ident(d.datname) "\
725 " FROM pg_catalog.pg_database d "\
726 " WHERE substring(pg_catalog.quote_ident(d.datname),1,%d)='%s' "\
727 " AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
729 #define Query_for_list_of_databases \
730 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
731 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
733 #define Query_for_list_of_tablespaces \
734 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
735 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
737 #define Query_for_list_of_encodings \
738 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
739 " FROM pg_catalog.pg_conversion "\
740 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
742 #define Query_for_list_of_languages \
743 "SELECT pg_catalog.quote_ident(lanname) "\
744 " FROM pg_catalog.pg_language "\
745 " WHERE lanname != 'internal' "\
746 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
748 #define Query_for_list_of_schemas \
749 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
750 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
752 #define Query_for_list_of_alter_system_set_vars \
754 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
755 " WHERE context != 'internal' "\
756 " UNION ALL SELECT 'all') ss "\
757 " WHERE substring(name,1,%d)='%s'"
759 #define Query_for_list_of_set_vars \
761 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
762 " WHERE context IN ('user', 'superuser') "\
763 " UNION ALL SELECT 'constraints' "\
764 " UNION ALL SELECT 'transaction' "\
765 " UNION ALL SELECT 'session' "\
766 " UNION ALL SELECT 'role' "\
767 " UNION ALL SELECT 'tablespace' "\
768 " UNION ALL SELECT 'all') ss "\
769 " WHERE substring(name,1,%d)='%s'"
771 #define Query_for_list_of_show_vars \
773 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
774 " UNION ALL SELECT 'session authorization' "\
775 " UNION ALL SELECT 'all') ss "\
776 " WHERE substring(name,1,%d)='%s'"
778 #define Query_for_list_of_roles \
779 " SELECT pg_catalog.quote_ident(rolname) "\
780 " FROM pg_catalog.pg_roles "\
781 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
783 #define Query_for_list_of_grant_roles \
784 " SELECT pg_catalog.quote_ident(rolname) "\
785 " FROM pg_catalog.pg_roles "\
786 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
787 " UNION ALL SELECT 'PUBLIC'"\
788 " UNION ALL SELECT 'CURRENT_USER'"\
789 " UNION ALL SELECT 'SESSION_USER'"
791 /* the silly-looking length condition is just to eat up the current word */
792 #define Query_for_table_owning_index \
793 "SELECT pg_catalog.quote_ident(c1.relname) "\
794 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
795 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
796 " and (%d = pg_catalog.length('%s'))"\
797 " and pg_catalog.quote_ident(c2.relname)='%s'"\
798 " and pg_catalog.pg_table_is_visible(c2.oid)"
800 /* the silly-looking length condition is just to eat up the current word */
801 #define Query_for_index_of_table \
802 "SELECT pg_catalog.quote_ident(c2.relname) "\
803 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
804 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
805 " and (%d = pg_catalog.length('%s'))"\
806 " and pg_catalog.quote_ident(c1.relname)='%s'"\
807 " and pg_catalog.pg_table_is_visible(c2.oid)"
809 /* the silly-looking length condition is just to eat up the current word */
810 #define Query_for_constraint_of_table \
811 "SELECT pg_catalog.quote_ident(conname) "\
812 " FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
813 " WHERE c1.oid=conrelid 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 #define Query_for_all_table_constraints \
818 "SELECT pg_catalog.quote_ident(conname) "\
819 " FROM pg_catalog.pg_constraint c "\
820 " WHERE c.conrelid <> 0 "
822 /* the silly-looking length condition is just to eat up the current word */
823 #define Query_for_constraint_of_type \
824 "SELECT pg_catalog.quote_ident(conname) "\
825 " FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
826 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
827 " and pg_catalog.quote_ident(t.typname)='%s'"\
828 " and pg_catalog.pg_type_is_visible(t.oid)"
830 /* the silly-looking length condition is just to eat up the current word */
831 #define Query_for_list_of_tables_for_constraint \
832 "SELECT pg_catalog.quote_ident(relname) "\
833 " FROM pg_catalog.pg_class"\
834 " WHERE (%d = pg_catalog.length('%s'))"\
836 " (SELECT conrelid FROM pg_catalog.pg_constraint "\
837 " WHERE pg_catalog.quote_ident(conname)='%s')"
839 /* the silly-looking length condition is just to eat up the current word */
840 #define Query_for_rule_of_table \
841 "SELECT pg_catalog.quote_ident(rulename) "\
842 " FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
843 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
844 " and pg_catalog.quote_ident(c1.relname)='%s'"\
845 " and pg_catalog.pg_table_is_visible(c1.oid)"
847 /* the silly-looking length condition is just to eat up the current word */
848 #define Query_for_list_of_tables_for_rule \
849 "SELECT pg_catalog.quote_ident(relname) "\
850 " FROM pg_catalog.pg_class"\
851 " WHERE (%d = pg_catalog.length('%s'))"\
853 " (SELECT ev_class FROM pg_catalog.pg_rewrite "\
854 " WHERE pg_catalog.quote_ident(rulename)='%s')"
856 /* the silly-looking length condition is just to eat up the current word */
857 #define Query_for_trigger_of_table \
858 "SELECT pg_catalog.quote_ident(tgname) "\
859 " FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
860 " WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
861 " and pg_catalog.quote_ident(c1.relname)='%s'"\
862 " and pg_catalog.pg_table_is_visible(c1.oid)"\
863 " and not tgisinternal"
865 /* the silly-looking length condition is just to eat up the current word */
866 #define Query_for_list_of_tables_for_trigger \
867 "SELECT pg_catalog.quote_ident(relname) "\
868 " FROM pg_catalog.pg_class"\
869 " WHERE (%d = pg_catalog.length('%s'))"\
871 " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
872 " WHERE pg_catalog.quote_ident(tgname)='%s')"
874 #define Query_for_list_of_ts_configurations \
875 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
876 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
878 #define Query_for_list_of_ts_dictionaries \
879 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
880 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
882 #define Query_for_list_of_ts_parsers \
883 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
884 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
886 #define Query_for_list_of_ts_templates \
887 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
888 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
890 #define Query_for_list_of_fdws \
891 " SELECT pg_catalog.quote_ident(fdwname) "\
892 " FROM pg_catalog.pg_foreign_data_wrapper "\
893 " WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
895 #define Query_for_list_of_servers \
896 " SELECT pg_catalog.quote_ident(srvname) "\
897 " FROM pg_catalog.pg_foreign_server "\
898 " WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
900 #define Query_for_list_of_user_mappings \
901 " SELECT pg_catalog.quote_ident(usename) "\
902 " FROM pg_catalog.pg_user_mappings "\
903 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
905 #define Query_for_list_of_access_methods \
906 " SELECT pg_catalog.quote_ident(amname) "\
907 " FROM pg_catalog.pg_am "\
908 " WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
910 #define Query_for_list_of_publications \
911 " SELECT pg_catalog.quote_ident(pubname) "\
912 " FROM pg_catalog.pg_publication "\
913 " WHERE substring(pg_catalog.quote_ident(pubname),1,%d)='%s'"
915 #define Query_for_list_of_subscriptions \
916 " SELECT pg_catalog.quote_ident(s.subname) "\
917 " FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "\
918 " WHERE substring(pg_catalog.quote_ident(s.subname),1,%d)='%s' "\
919 " AND d.datname = pg_catalog.current_database() "\
920 " AND s.subdbid = d.oid"
922 /* the silly-looking length condition is just to eat up the current word */
923 #define Query_for_list_of_arguments \
924 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
925 " FROM pg_catalog.pg_proc "\
926 " WHERE (%d = pg_catalog.length('%s'))"\
927 " AND (pg_catalog.quote_ident(proname)='%s'"\
928 " OR '\"' || proname || '\"'='%s') "\
929 " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
931 /* the silly-looking length condition is just to eat up the current word */
932 #define Query_for_list_of_arguments_with_schema \
933 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
934 " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
935 " WHERE (%d = pg_catalog.length('%s'))"\
936 " AND n.oid = p.pronamespace "\
937 " AND (pg_catalog.quote_ident(proname)='%s' "\
938 " OR '\"' || proname || '\"' ='%s') "\
939 " AND (pg_catalog.quote_ident(nspname)='%s' "\
940 " OR '\"' || nspname || '\"' ='%s') "
942 #define Query_for_list_of_extensions \
943 " SELECT pg_catalog.quote_ident(extname) "\
944 " FROM pg_catalog.pg_extension "\
945 " WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
947 #define Query_for_list_of_available_extensions \
948 " SELECT pg_catalog.quote_ident(name) "\
949 " FROM pg_catalog.pg_available_extensions "\
950 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
952 /* the silly-looking length condition is just to eat up the current word */
953 #define Query_for_list_of_available_extension_versions \
954 " SELECT pg_catalog.quote_ident(version) "\
955 " FROM pg_catalog.pg_available_extension_versions "\
956 " WHERE (%d = pg_catalog.length('%s'))"\
957 " AND pg_catalog.quote_ident(name)='%s'"
959 /* the silly-looking length condition is just to eat up the current word */
960 #define Query_for_list_of_available_extension_versions_with_TO \
961 " SELECT 'TO ' || pg_catalog.quote_ident(version) "\
962 " FROM pg_catalog.pg_available_extension_versions "\
963 " WHERE (%d = pg_catalog.length('%s'))"\
964 " AND pg_catalog.quote_ident(name)='%s'"
966 #define Query_for_list_of_prepared_statements \
967 " SELECT pg_catalog.quote_ident(name) "\
968 " FROM pg_catalog.pg_prepared_statements "\
969 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
971 #define Query_for_list_of_event_triggers \
972 " SELECT pg_catalog.quote_ident(evtname) "\
973 " FROM pg_catalog.pg_event_trigger "\
974 " WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
976 #define Query_for_list_of_tablesample_methods \
977 " SELECT pg_catalog.quote_ident(proname) "\
978 " FROM pg_catalog.pg_proc "\
979 " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
980 " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
981 " substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
983 #define Query_for_list_of_policies \
984 " SELECT pg_catalog.quote_ident(polname) "\
985 " FROM pg_catalog.pg_policy "\
986 " WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
988 #define Query_for_list_of_tables_for_policy \
989 "SELECT pg_catalog.quote_ident(relname) "\
990 " FROM pg_catalog.pg_class"\
991 " WHERE (%d = pg_catalog.length('%s'))"\
993 " (SELECT polrelid FROM pg_catalog.pg_policy "\
994 " WHERE pg_catalog.quote_ident(polname)='%s')"
996 #define Query_for_enum \
997 " SELECT name FROM ( "\
998 " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
999 " FROM pg_catalog.pg_settings "\
1000 " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
1002 " SELECT 'DEFAULT' ) ss "\
1003 " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
1005 /* the silly-looking length condition is just to eat up the current word */
1006 #define Query_for_partition_of_table \
1007 "SELECT pg_catalog.quote_ident(c2.relname) "\
1008 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i"\
1009 " WHERE c1.oid=i.inhparent and i.inhrelid=c2.oid"\
1010 " and (%d = pg_catalog.length('%s'))"\
1011 " and pg_catalog.quote_ident(c1.relname)='%s'"\
1012 " and pg_catalog.pg_table_is_visible(c2.oid)"\
1013 " and c2.relispartition = 'true'"
1016 * This is a list of all "things" in Pgsql, which can show up after CREATE or
1017 * DROP; and there is also a query to get a list of them.
1023 const char *query; /* simple query, or NULL */
1024 const SchemaQuery *squery; /* schema query, or NULL */
1025 const bits32 flags; /* visibility flags, see below */
1028 #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
1029 #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
1030 #define THING_NO_ALTER (1 << 2) /* should not show up after ALTER */
1031 #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
1033 static const pgsql_thing_t words_after_create[] = {
1034 {"ACCESS METHOD", NULL, NULL, THING_NO_ALTER},
1035 {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
1036 {"CAST", NULL, NULL}, /* Casts have complex structures for names, so
1038 {"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'"},
1041 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
1042 * to be used only by pg_dump.
1044 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
1045 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
1046 {"DATABASE", Query_for_list_of_databases},
1047 {"DEFAULT PRIVILEGES", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1048 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
1049 {"DOMAIN", NULL, &Query_for_list_of_domains},
1050 {"EVENT TRIGGER", NULL, NULL},
1051 {"EXTENSION", Query_for_list_of_extensions},
1052 {"FOREIGN DATA WRAPPER", NULL, NULL},
1053 {"FOREIGN TABLE", NULL, NULL},
1054 {"FUNCTION", NULL, &Query_for_list_of_functions},
1055 {"GROUP", Query_for_list_of_roles},
1056 {"INDEX", NULL, &Query_for_list_of_indexes},
1057 {"LANGUAGE", Query_for_list_of_languages},
1058 {"LARGE OBJECT", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1059 {"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
1060 {"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a
1062 {"OWNED", NULL, NULL, THING_NO_CREATE | THING_NO_ALTER}, /* for DROP OWNED BY ... */
1063 {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
1064 {"POLICY", NULL, NULL},
1065 {"PROCEDURE", NULL, &Query_for_list_of_procedures},
1066 {"PUBLICATION", Query_for_list_of_publications},
1067 {"ROLE", Query_for_list_of_roles},
1068 {"ROUTINE", NULL, &Query_for_list_of_routines, THING_NO_CREATE},
1069 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
1070 {"SCHEMA", Query_for_list_of_schemas},
1071 {"SEQUENCE", NULL, &Query_for_list_of_sequences},
1072 {"SERVER", Query_for_list_of_servers},
1073 {"STATISTICS", NULL, &Query_for_list_of_statistics},
1074 {"SUBSCRIPTION", Query_for_list_of_subscriptions},
1075 {"SYSTEM", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1076 {"TABLE", NULL, &Query_for_list_of_tables},
1077 {"TABLESPACE", Query_for_list_of_tablespaces},
1078 {"TEMP", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE
1080 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
1081 {"TEMPORARY", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMPORARY
1083 {"TEXT SEARCH", NULL, NULL},
1084 {"TRANSFORM", NULL, NULL},
1085 {"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"},
1086 {"TYPE", NULL, &Query_for_list_of_datatypes},
1087 {"UNIQUE", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNIQUE
1089 {"UNLOGGED", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNLOGGED
1091 {"USER", Query_for_list_of_roles " UNION SELECT 'MAPPING FOR'"},
1092 {"USER MAPPING FOR", NULL, NULL},
1093 {"VIEW", NULL, &Query_for_list_of_views},
1094 {NULL} /* end of list */
1098 /* Forward declaration of functions */
1099 static char **psql_completion(const char *text, int start, int end);
1100 static char *create_command_generator(const char *text, int state);
1101 static char *drop_command_generator(const char *text, int state);
1102 static char *alter_command_generator(const char *text, int state);
1103 static char *complete_from_query(const char *text, int state);
1104 static char *complete_from_schema_query(const char *text, int state);
1105 static char *_complete_from_query(int is_schema_query,
1106 const char *text, int state);
1107 static char *complete_from_list(const char *text, int state);
1108 static char *complete_from_const(const char *text, int state);
1109 static void append_variable_names(char ***varnames, int *nvars,
1110 int *maxvars, const char *varname,
1111 const char *prefix, const char *suffix);
1112 static char **complete_from_variables(const char *text,
1113 const char *prefix, const char *suffix, bool need_value);
1114 static char *complete_from_files(const char *text, int state);
1116 static char *pg_strdup_keyword_case(const char *s, const char *ref);
1117 static char *escape_string(const char *text);
1118 static PGresult *exec_query(const char *query);
1120 static char **get_previous_words(int point, char **buffer, int *nwords);
1122 static char *get_guctype(const char *varname);
1125 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
1126 static char *dequote_file_name(char *text, char quote_char);
1131 * Initialize the readline library for our purposes.
1134 initialize_readline(void)
1136 rl_readline_name = (char *) pset.progname;
1137 rl_attempted_completion_function = psql_completion;
1139 rl_basic_word_break_characters = WORD_BREAKS;
1141 completion_max_records = 1000;
1144 * There is a variable rl_completion_query_items for this but apparently
1145 * it's not defined everywhere.
1150 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1151 * using case-insensitive or case-sensitive comparisons.
1153 * If pattern is NULL, it's a wild card that matches any word.
1154 * If pattern begins with '!', the result is negated, ie we check that 'word'
1155 * does *not* match any alternative appearing in the rest of 'pattern'.
1156 * Any alternative can end with '*' which is a wild card, i.e., it means
1157 * match any word that matches the characters so far. (We do not currently
1158 * support '*' elsewhere than the end of an alternative.)
1160 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1161 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1162 * just be written directly in patterns.)
1164 #define MatchAny NULL
1165 #define MatchAnyExcept(pattern) ("!" pattern)
1168 word_matches_internal(const char *pattern,
1170 bool case_sensitive)
1175 /* NULL pattern matches anything. */
1176 if (pattern == NULL)
1179 /* Handle negated patterns from the MatchAnyExcept macro. */
1180 if (*pattern == '!')
1181 return !word_matches_internal(pattern + 1, word, case_sensitive);
1183 /* Else consider each alternative in the pattern. */
1184 wordlen = strlen(word);
1189 /* Find end of current alternative. */
1191 while (*c != '\0' && *c != '|')
1193 /* Was there a wild card? (Assumes first alternative is not empty) */
1196 /* Yes, wildcard match? */
1197 patternlen = c - pattern - 1;
1198 if (wordlen >= patternlen &&
1200 strncmp(word, pattern, patternlen) == 0 :
1201 pg_strncasecmp(word, pattern, patternlen) == 0))
1206 /* No, plain match? */
1207 patternlen = c - pattern;
1208 if (wordlen == patternlen &&
1210 strncmp(word, pattern, wordlen) == 0 :
1211 pg_strncasecmp(word, pattern, wordlen) == 0))
1214 /* Out of alternatives? */
1217 /* Nope, try next alternative. */
1225 * There are enough matching calls below that it seems worth having these two
1226 * interface routines rather than including a third parameter in every call.
1228 * word_matches --- match case-insensitively.
1231 word_matches(const char *pattern, const char *word)
1233 return word_matches_internal(pattern, word, false);
1237 * word_matches_cs --- match case-sensitively.
1240 word_matches_cs(const char *pattern, const char *word)
1242 return word_matches_internal(pattern, word, true);
1246 * Check if the final character of 's' is 'c'.
1249 ends_with(const char *s, char c)
1251 size_t length = strlen(s);
1253 return (length > 0 && s[length - 1] == c);
1257 * The completion function.
1259 * According to readline spec this gets passed the text entered so far and its
1260 * start and end positions in the readline buffer. The return value is some
1261 * partially obscure list format that can be generated by readline's
1262 * completion_matches() function, so we don't have to worry about it.
1265 psql_completion(const char *text, int start, int end)
1267 /* This is the variable we'll return. */
1268 char **matches = NULL;
1270 /* Workspace for parsed words. */
1273 /* This array will contain pointers to parsed words. */
1274 char **previous_words;
1276 /* The number of words found on the input line. */
1277 int previous_words_count;
1280 * For compactness, we use these macros to reference previous_words[].
1281 * Caution: do not access a previous_words[] entry without having checked
1282 * previous_words_count to be sure it's valid. In most cases below, that
1283 * check is implicit in a TailMatches() or similar macro, but in some
1284 * places we have to check it explicitly.
1286 #define prev_wd (previous_words[0])
1287 #define prev2_wd (previous_words[1])
1288 #define prev3_wd (previous_words[2])
1289 #define prev4_wd (previous_words[3])
1290 #define prev5_wd (previous_words[4])
1291 #define prev6_wd (previous_words[5])
1292 #define prev7_wd (previous_words[6])
1293 #define prev8_wd (previous_words[7])
1294 #define prev9_wd (previous_words[8])
1296 /* Macros for matching the last N words before point, case-insensitively. */
1297 #define TailMatches1(p1) \
1298 (previous_words_count >= 1 && \
1299 word_matches(p1, prev_wd))
1301 #define TailMatches2(p2, p1) \
1302 (previous_words_count >= 2 && \
1303 word_matches(p1, prev_wd) && \
1304 word_matches(p2, prev2_wd))
1306 #define TailMatches3(p3, p2, p1) \
1307 (previous_words_count >= 3 && \
1308 word_matches(p1, prev_wd) && \
1309 word_matches(p2, prev2_wd) && \
1310 word_matches(p3, prev3_wd))
1312 #define TailMatches4(p4, p3, p2, p1) \
1313 (previous_words_count >= 4 && \
1314 word_matches(p1, prev_wd) && \
1315 word_matches(p2, prev2_wd) && \
1316 word_matches(p3, prev3_wd) && \
1317 word_matches(p4, prev4_wd))
1319 #define TailMatches5(p5, p4, p3, p2, p1) \
1320 (previous_words_count >= 5 && \
1321 word_matches(p1, prev_wd) && \
1322 word_matches(p2, prev2_wd) && \
1323 word_matches(p3, prev3_wd) && \
1324 word_matches(p4, prev4_wd) && \
1325 word_matches(p5, prev5_wd))
1327 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1328 (previous_words_count >= 6 && \
1329 word_matches(p1, prev_wd) && \
1330 word_matches(p2, prev2_wd) && \
1331 word_matches(p3, prev3_wd) && \
1332 word_matches(p4, prev4_wd) && \
1333 word_matches(p5, prev5_wd) && \
1334 word_matches(p6, prev6_wd))
1336 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1337 (previous_words_count >= 7 && \
1338 word_matches(p1, prev_wd) && \
1339 word_matches(p2, prev2_wd) && \
1340 word_matches(p3, prev3_wd) && \
1341 word_matches(p4, prev4_wd) && \
1342 word_matches(p5, prev5_wd) && \
1343 word_matches(p6, prev6_wd) && \
1344 word_matches(p7, prev7_wd))
1346 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1347 (previous_words_count >= 8 && \
1348 word_matches(p1, prev_wd) && \
1349 word_matches(p2, prev2_wd) && \
1350 word_matches(p3, prev3_wd) && \
1351 word_matches(p4, prev4_wd) && \
1352 word_matches(p5, prev5_wd) && \
1353 word_matches(p6, prev6_wd) && \
1354 word_matches(p7, prev7_wd) && \
1355 word_matches(p8, prev8_wd))
1357 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1358 (previous_words_count >= 9 && \
1359 word_matches(p1, prev_wd) && \
1360 word_matches(p2, prev2_wd) && \
1361 word_matches(p3, prev3_wd) && \
1362 word_matches(p4, prev4_wd) && \
1363 word_matches(p5, prev5_wd) && \
1364 word_matches(p6, prev6_wd) && \
1365 word_matches(p7, prev7_wd) && \
1366 word_matches(p8, prev8_wd) && \
1367 word_matches(p9, prev9_wd))
1369 /* Macros for matching the last N words before point, case-sensitively. */
1370 #define TailMatchesCS1(p1) \
1371 (previous_words_count >= 1 && \
1372 word_matches_cs(p1, prev_wd))
1373 #define TailMatchesCS2(p2, p1) \
1374 (previous_words_count >= 2 && \
1375 word_matches_cs(p1, prev_wd) && \
1376 word_matches_cs(p2, prev2_wd))
1377 #define TailMatchesCS3(p3, p2, p1) \
1378 (previous_words_count >= 3 && \
1379 word_matches_cs(p1, prev_wd) && \
1380 word_matches_cs(p2, prev2_wd) && \
1381 word_matches_cs(p3, prev3_wd))
1382 #define TailMatchesCS4(p4, p3, p2, p1) \
1383 (previous_words_count >= 4 && \
1384 word_matches_cs(p1, prev_wd) && \
1385 word_matches_cs(p2, prev2_wd) && \
1386 word_matches_cs(p3, prev3_wd) && \
1387 word_matches_cs(p4, prev4_wd))
1390 * Macros for matching N words beginning at the start of the line,
1391 * case-insensitively.
1393 #define Matches1(p1) \
1394 (previous_words_count == 1 && \
1396 #define Matches2(p1, p2) \
1397 (previous_words_count == 2 && \
1398 TailMatches2(p1, p2))
1399 #define Matches3(p1, p2, p3) \
1400 (previous_words_count == 3 && \
1401 TailMatches3(p1, p2, p3))
1402 #define Matches4(p1, p2, p3, p4) \
1403 (previous_words_count == 4 && \
1404 TailMatches4(p1, p2, p3, p4))
1405 #define Matches5(p1, p2, p3, p4, p5) \
1406 (previous_words_count == 5 && \
1407 TailMatches5(p1, p2, p3, p4, p5))
1408 #define Matches6(p1, p2, p3, p4, p5, p6) \
1409 (previous_words_count == 6 && \
1410 TailMatches6(p1, p2, p3, p4, p5, p6))
1411 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1412 (previous_words_count == 7 && \
1413 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1414 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1415 (previous_words_count == 8 && \
1416 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1417 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1418 (previous_words_count == 9 && \
1419 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1422 * Macros for matching N words at the start of the line, regardless of
1423 * what is after them, case-insensitively.
1425 #define HeadMatches1(p1) \
1426 (previous_words_count >= 1 && \
1427 word_matches(p1, previous_words[previous_words_count - 1]))
1429 #define HeadMatches2(p1, p2) \
1430 (previous_words_count >= 2 && \
1431 word_matches(p1, previous_words[previous_words_count - 1]) && \
1432 word_matches(p2, previous_words[previous_words_count - 2]))
1434 #define HeadMatches3(p1, p2, p3) \
1435 (previous_words_count >= 3 && \
1436 word_matches(p1, previous_words[previous_words_count - 1]) && \
1437 word_matches(p2, previous_words[previous_words_count - 2]) && \
1438 word_matches(p3, previous_words[previous_words_count - 3]))
1440 /* Known command-starting keywords. */
1441 static const char *const sql_commands[] = {
1442 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CALL", "CHECKPOINT", "CLOSE", "CLUSTER",
1443 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1444 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1445 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1446 "MOVE", "NOTIFY", "PREPARE",
1447 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1448 "RESET", "REVOKE", "ROLLBACK",
1449 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1450 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1454 /* psql's backslash commands. */
1455 static const char *const backslash_commands[] = {
1457 "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1458 "\\copyright", "\\crosstabview",
1459 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1460 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1461 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1462 "\\dm", "\\dn", "\\do", "\\dO", "\\dp",
1463 "\\drds", "\\dRs", "\\dRp", "\\ds", "\\dS",
1464 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1465 "\\e", "\\echo", "\\ef", "\\elif", "\\else", "\\encoding",
1466 "\\endif", "\\errverbose", "\\ev",
1468 "\\g", "\\gdesc", "\\gexec", "\\gset", "\\gx",
1469 "\\h", "\\help", "\\H",
1470 "\\i", "\\if", "\\ir",
1471 "\\l", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1473 "\\p", "\\password", "\\prompt", "\\pset",
1476 "\\s", "\\set", "\\setenv", "\\sf", "\\sv",
1477 "\\t", "\\T", "\\timing",
1486 (void) end; /* "end" is not used */
1488 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1489 rl_completion_append_character = ' ';
1492 /* Clear a few things. */
1493 completion_charp = NULL;
1494 completion_charpp = NULL;
1495 completion_info_charp = NULL;
1496 completion_info_charp2 = NULL;
1499 * Scan the input line to extract the words before our current position.
1500 * According to those we'll make some smart decisions on what the user is
1501 * probably intending to type.
1503 previous_words = get_previous_words(start,
1505 &previous_words_count);
1507 /* If current word is a backslash command, offer completions for that */
1508 if (text[0] == '\\')
1509 COMPLETE_WITH_LIST_CS(backslash_commands);
1511 /* If current word is a variable interpolation, handle that case */
1512 else if (text[0] == ':' && text[1] != ':')
1514 if (text[1] == '\'')
1515 matches = complete_from_variables(text, ":'", "'", true);
1516 else if (text[1] == '"')
1517 matches = complete_from_variables(text, ":\"", "\"", true);
1519 matches = complete_from_variables(text, ":", "", true);
1522 /* If no previous word, suggest one of the basic sql commands */
1523 else if (previous_words_count == 0)
1524 COMPLETE_WITH_LIST(sql_commands);
1527 /* complete with something you can create */
1528 else if (TailMatches1("CREATE"))
1529 matches = completion_matches(text, create_command_generator);
1531 /* DROP, but not DROP embedded in other commands */
1532 /* complete with something you can drop */
1533 else if (Matches1("DROP"))
1534 matches = completion_matches(text, drop_command_generator);
1539 else if (Matches2("ALTER", "TABLE"))
1540 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1541 "UNION SELECT 'ALL IN TABLESPACE'");
1543 /* ALTER something */
1544 else if (Matches1("ALTER"))
1545 matches = completion_matches(text, alter_command_generator);
1546 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1547 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1548 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1549 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1550 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1551 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1552 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1553 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1554 COMPLETE_WITH_CONST("SET TABLESPACE");
1555 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
1556 else if (Matches3("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
1557 COMPLETE_WITH_CONST("(");
1558 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> (...) */
1559 else if (Matches4("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny))
1561 if (ends_with(prev_wd, ')'))
1562 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1564 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1566 /* ALTER PUBLICATION <name> */
1567 else if (Matches3("ALTER", "PUBLICATION", MatchAny))
1568 COMPLETE_WITH_LIST5("ADD TABLE", "DROP TABLE", "OWNER TO", "RENAME TO", "SET");
1569 /* ALTER PUBLICATION <name> SET */
1570 else if (Matches4("ALTER", "PUBLICATION", MatchAny, "SET"))
1571 COMPLETE_WITH_LIST2("(", "TABLE");
1572 /* ALTER PUBLICATION <name> SET ( */
1573 else if (HeadMatches3("ALTER", "PUBLICATION", MatchAny) && TailMatches2("SET", "("))
1574 COMPLETE_WITH_CONST("publish");
1575 /* ALTER SUBSCRIPTION <name> */
1576 else if (Matches3("ALTER", "SUBSCRIPTION", MatchAny))
1577 COMPLETE_WITH_LIST7("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
1578 "RENAME TO", "REFRESH PUBLICATION", "SET");
1579 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION */
1580 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1581 TailMatches2("REFRESH", "PUBLICATION"))
1582 COMPLETE_WITH_CONST("WITH (");
1583 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
1584 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1585 TailMatches4("REFRESH", "PUBLICATION", "WITH", "("))
1586 COMPLETE_WITH_CONST("copy_data");
1587 /* ALTER SUBSCRIPTION <name> SET */
1588 else if (Matches4("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
1589 COMPLETE_WITH_LIST2("(", "PUBLICATION");
1590 /* ALTER SUBSCRIPTION <name> SET ( */
1591 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "("))
1592 COMPLETE_WITH_LIST2("slot_name", "synchronous_commit");
1593 /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
1594 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "PUBLICATION"))
1596 /* complete with nothing here as this refers to remote publications */
1598 /* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> */
1599 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1600 TailMatches3("SET", "PUBLICATION", MatchAny))
1601 COMPLETE_WITH_CONST("WITH (");
1602 /* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> WITH ( */
1603 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1604 TailMatches5("SET", "PUBLICATION", MatchAny, "WITH", "("))
1605 COMPLETE_WITH_LIST2("copy_data", "refresh");
1606 /* ALTER SCHEMA <name> */
1607 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1608 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1610 /* ALTER COLLATION <name> */
1611 else if (Matches3("ALTER", "COLLATION", MatchAny))
1612 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1614 /* ALTER CONVERSION <name> */
1615 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1616 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1618 /* ALTER DATABASE <name> */
1619 else if (Matches3("ALTER", "DATABASE", MatchAny))
1620 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1621 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1622 "CONNECTION LIMIT");
1624 /* ALTER EVENT TRIGGER */
1625 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1626 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1628 /* ALTER EVENT TRIGGER <name> */
1629 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1630 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1632 /* ALTER EVENT TRIGGER <name> ENABLE */
1633 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1634 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1636 /* ALTER EXTENSION <name> */
1637 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1638 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1640 /* ALTER EXTENSION <name> UPDATE */
1641 else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
1643 completion_info_charp = prev2_wd;
1644 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
1647 /* ALTER EXTENSION <name> UPDATE TO */
1648 else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
1650 completion_info_charp = prev3_wd;
1651 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
1655 else if (Matches2("ALTER", "FOREIGN"))
1656 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1658 /* ALTER FOREIGN DATA WRAPPER <name> */
1659 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1660 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1662 /* ALTER FOREIGN TABLE <name> */
1663 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1665 static const char *const list_ALTER_FOREIGN_TABLE[] =
1666 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1667 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1668 "VALIDATE CONSTRAINT", NULL};
1670 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1674 else if (Matches2("ALTER", "INDEX"))
1675 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1676 "UNION SELECT 'ALL IN TABLESPACE'");
1677 /* ALTER INDEX <name> */
1678 else if (Matches3("ALTER", "INDEX", MatchAny))
1679 COMPLETE_WITH_LIST5("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET", "RESET");
1680 /* ALTER INDEX <name> ALTER COLUMN <colnum> */
1681 else if (Matches6("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
1682 COMPLETE_WITH_CONST("SET STATISTICS");
1683 /* ALTER INDEX <name> SET */
1684 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1685 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1686 /* ALTER INDEX <name> RESET */
1687 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1688 COMPLETE_WITH_CONST("(");
1689 /* ALTER INDEX <foo> SET|RESET ( */
1690 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1691 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1692 "gin_pending_list_limit");
1693 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1694 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1695 "gin_pending_list_limit =");
1697 /* ALTER LANGUAGE <name> */
1698 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1699 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1701 /* ALTER LARGE OBJECT <oid> */
1702 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1703 COMPLETE_WITH_CONST("OWNER TO");
1705 /* ALTER MATERIALIZED VIEW */
1706 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1707 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1708 "UNION SELECT 'ALL IN TABLESPACE'");
1710 /* ALTER USER,ROLE <name> */
1711 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1712 !TailMatches2("USER", "MAPPING"))
1714 static const char *const list_ALTERUSER[] =
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", "WITH", NULL};
1722 COMPLETE_WITH_LIST(list_ALTERUSER);
1725 /* ALTER USER,ROLE <name> WITH */
1726 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1728 /* Similar to the above, but don't complete "WITH" again. */
1729 static const char *const list_ALTERUSER_WITH[] =
1730 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1731 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1732 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1733 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1734 "REPLICATION", "RESET", "SET", "SUPERUSER",
1735 "VALID UNTIL", NULL};
1737 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1740 /* ALTER DEFAULT PRIVILEGES */
1741 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1742 COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
1743 /* ALTER DEFAULT PRIVILEGES FOR */
1744 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1745 COMPLETE_WITH_CONST("ROLE");
1746 /* ALTER DEFAULT PRIVILEGES IN */
1747 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1748 COMPLETE_WITH_CONST("SCHEMA");
1749 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1750 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1752 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
1753 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1754 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1756 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
1757 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1758 else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1760 COMPLETE_WITH_CONST("ROLE");
1761 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
1762 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1763 else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1764 MatchAny, "IN", "SCHEMA", MatchAny) ||
1765 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1766 MatchAny, "FOR", "ROLE|USER", MatchAny))
1767 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1768 /* ALTER DOMAIN <name> */
1769 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1770 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1771 "VALIDATE CONSTRAINT");
1772 /* ALTER DOMAIN <sth> DROP */
1773 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1774 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1775 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1776 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1778 completion_info_charp = prev3_wd;
1779 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1781 /* ALTER DOMAIN <sth> RENAME */
1782 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1783 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1784 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1785 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1786 COMPLETE_WITH_CONST("TO");
1788 /* ALTER DOMAIN <sth> SET */
1789 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1790 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1791 /* ALTER SEQUENCE <name> */
1792 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1794 static const char *const list_ALTERSEQUENCE[] =
1795 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1796 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1798 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1800 /* ALTER SEQUENCE <name> NO */
1801 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1802 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1803 /* ALTER SERVER <name> */
1804 else if (Matches3("ALTER", "SERVER", MatchAny))
1805 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1806 /* ALTER SERVER <name> VERSION <version> */
1807 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1808 COMPLETE_WITH_CONST("OPTIONS");
1809 /* ALTER SYSTEM SET, RESET, RESET ALL */
1810 else if (Matches2("ALTER", "SYSTEM"))
1811 COMPLETE_WITH_LIST2("SET", "RESET");
1812 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1813 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1814 else if (Matches4("ALTER", "SYSTEM", "SET", MatchAny))
1815 COMPLETE_WITH_CONST("TO");
1816 /* ALTER VIEW <name> */
1817 else if (Matches3("ALTER", "VIEW", MatchAny))
1818 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1820 /* ALTER MATERIALIZED VIEW <name> */
1821 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1822 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1825 /* ALTER POLICY <name> */
1826 else if (Matches2("ALTER", "POLICY"))
1827 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1828 /* ALTER POLICY <name> ON */
1829 else if (Matches3("ALTER", "POLICY", MatchAny))
1830 COMPLETE_WITH_CONST("ON");
1831 /* ALTER POLICY <name> ON <table> */
1832 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1834 completion_info_charp = prev2_wd;
1835 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1837 /* ALTER POLICY <name> ON <table> - show options */
1838 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1839 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1840 /* ALTER POLICY <name> ON <table> TO <role> */
1841 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1842 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1843 /* ALTER POLICY <name> ON <table> USING ( */
1844 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1845 COMPLETE_WITH_CONST("(");
1846 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1847 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1848 COMPLETE_WITH_CONST("(");
1850 /* ALTER RULE <name>, add ON */
1851 else if (Matches3("ALTER", "RULE", MatchAny))
1852 COMPLETE_WITH_CONST("ON");
1854 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1855 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1857 completion_info_charp = prev2_wd;
1858 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1861 /* ALTER RULE <name> ON <name> */
1862 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1863 COMPLETE_WITH_CONST("RENAME TO");
1865 /* ALTER STATISTICS <name> */
1866 else if (Matches3("ALTER", "STATISTICS", MatchAny))
1867 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1869 /* ALTER TRIGGER <name>, add ON */
1870 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1871 COMPLETE_WITH_CONST("ON");
1873 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1875 completion_info_charp = prev2_wd;
1876 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1880 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1882 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1883 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1885 /* ALTER TRIGGER <name> ON <name> */
1886 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1887 COMPLETE_WITH_CONST("RENAME TO");
1890 * If we detect ALTER TABLE <name>, suggest sub commands
1892 else if (Matches3("ALTER", "TABLE", MatchAny))
1894 static const char *const list_ALTER2[] =
1895 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1896 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1897 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", "ATTACH PARTITION",
1898 "DETACH PARTITION", NULL};
1900 COMPLETE_WITH_LIST(list_ALTER2);
1902 /* ALTER TABLE xxx ENABLE */
1903 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1904 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1906 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1907 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1908 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1910 completion_info_charp = prev3_wd;
1911 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1913 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1915 completion_info_charp = prev4_wd;
1916 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1918 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1920 completion_info_charp = prev3_wd;
1921 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1923 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1925 completion_info_charp = prev4_wd;
1926 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1928 /* ALTER TABLE xxx INHERIT */
1929 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1930 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1931 /* ALTER TABLE xxx NO INHERIT */
1932 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1933 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1934 /* ALTER TABLE xxx DISABLE */
1935 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1936 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1937 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1939 completion_info_charp = prev3_wd;
1940 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1942 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1944 completion_info_charp = prev3_wd;
1945 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1948 /* ALTER TABLE xxx ALTER */
1949 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1950 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1952 /* ALTER TABLE xxx RENAME */
1953 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1954 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1955 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1956 COMPLETE_WITH_ATTR(prev3_wd, "");
1958 /* ALTER TABLE xxx RENAME yyy */
1959 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1960 COMPLETE_WITH_CONST("TO");
1962 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1963 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1964 COMPLETE_WITH_CONST("TO");
1966 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1967 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1968 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1969 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1970 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1971 COMPLETE_WITH_ATTR(prev3_wd, "");
1974 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1975 * provide list of constraints
1977 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1979 completion_info_charp = prev3_wd;
1980 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1982 /* ALTER TABLE ALTER [COLUMN] <foo> */
1983 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1984 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1985 COMPLETE_WITH_LIST6("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
1986 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1987 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1988 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1989 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1990 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1991 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1992 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1993 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1994 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1995 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1996 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1997 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1998 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1999 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
2000 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
2001 COMPLETE_WITH_LIST3("DEFAULT", "IDENTITY", "NOT NULL");
2002 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
2003 COMPLETE_WITH_CONST("ON");
2004 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
2006 completion_info_charp = prev3_wd;
2007 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2009 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
2010 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
2011 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
2015 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
2018 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
2019 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2020 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
2021 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
2022 COMPLETE_WITH_CONST("OIDS");
2023 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
2024 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
2025 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
2026 /* ALTER TABLE <foo> RESET */
2027 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
2028 COMPLETE_WITH_CONST("(");
2029 /* ALTER TABLE <foo> SET|RESET ( */
2030 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
2032 static const char *const list_TABLEOPTIONS[] =
2034 "autovacuum_analyze_scale_factor",
2035 "autovacuum_analyze_threshold",
2036 "autovacuum_enabled",
2037 "autovacuum_freeze_max_age",
2038 "autovacuum_freeze_min_age",
2039 "autovacuum_freeze_table_age",
2040 "autovacuum_multixact_freeze_max_age",
2041 "autovacuum_multixact_freeze_min_age",
2042 "autovacuum_multixact_freeze_table_age",
2043 "autovacuum_vacuum_cost_delay",
2044 "autovacuum_vacuum_cost_limit",
2045 "autovacuum_vacuum_scale_factor",
2046 "autovacuum_vacuum_threshold",
2049 "log_autovacuum_min_duration",
2050 "toast.autovacuum_enabled",
2051 "toast.autovacuum_freeze_max_age",
2052 "toast.autovacuum_freeze_min_age",
2053 "toast.autovacuum_freeze_table_age",
2054 "toast.autovacuum_multixact_freeze_max_age",
2055 "toast.autovacuum_multixact_freeze_min_age",
2056 "toast.autovacuum_multixact_freeze_table_age",
2057 "toast.autovacuum_vacuum_cost_delay",
2058 "toast.autovacuum_vacuum_cost_limit",
2059 "toast.autovacuum_vacuum_scale_factor",
2060 "toast.autovacuum_vacuum_threshold",
2061 "toast.log_autovacuum_min_duration",
2062 "user_catalog_table",
2066 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
2068 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
2070 completion_info_charp = prev5_wd;
2071 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2073 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
2074 COMPLETE_WITH_CONST("INDEX");
2075 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
2076 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
2077 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
2078 COMPLETE_WITH_CONST("IDENTITY");
2081 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
2084 else if (Matches5("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
2085 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2086 /* Limited completion support for partition bound specification */
2087 else if (TailMatches3("ATTACH", "PARTITION", MatchAny))
2088 COMPLETE_WITH_LIST2("FOR VALUES", "DEFAULT");
2089 else if (TailMatches2("FOR", "VALUES"))
2090 COMPLETE_WITH_LIST3("FROM (", "IN (", "WITH (");
2093 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
2094 * partitions of <foo>.
2096 else if (Matches5("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
2098 completion_info_charp = prev3_wd;
2099 COMPLETE_WITH_QUERY(Query_for_partition_of_table);
2102 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
2103 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
2104 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
2105 /* ALTER TABLESPACE <foo> SET|RESET */
2106 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
2107 COMPLETE_WITH_CONST("(");
2108 /* ALTER TABLESPACE <foo> SET|RESET ( */
2109 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
2110 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
2111 "effective_io_concurrency");
2113 /* ALTER TEXT SEARCH */
2114 else if (Matches3("ALTER", "TEXT", "SEARCH"))
2115 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2116 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
2117 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
2118 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
2119 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
2120 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2121 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
2123 "OWNER TO", "RENAME TO", "SET SCHEMA");
2125 /* complete ALTER TYPE <foo> with actions */
2126 else if (Matches3("ALTER", "TYPE", MatchAny))
2127 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
2129 "OWNER TO", "RENAME", "SET SCHEMA");
2130 /* complete ALTER TYPE <foo> ADD with actions */
2131 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
2132 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
2133 /* ALTER TYPE <foo> RENAME */
2134 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
2135 COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
2136 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
2137 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
2138 COMPLETE_WITH_CONST("TO");
2141 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
2144 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
2145 COMPLETE_WITH_ATTR(prev3_wd, "");
2146 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
2147 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
2148 COMPLETE_WITH_CONST("TYPE");
2149 /* complete ALTER GROUP <foo> */
2150 else if (Matches3("ALTER", "GROUP", MatchAny))
2151 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
2152 /* complete ALTER GROUP <foo> ADD|DROP with USER */
2153 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
2154 COMPLETE_WITH_CONST("USER");
2155 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
2156 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
2157 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2160 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
2162 else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
2163 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
2166 else if (Matches1("BEGIN"))
2167 COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2169 else if (Matches1("END|ABORT"))
2170 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
2172 else if (Matches1("COMMIT"))
2173 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
2174 /* RELEASE SAVEPOINT */
2175 else if (Matches1("RELEASE"))
2176 COMPLETE_WITH_CONST("SAVEPOINT");
2178 else if (Matches1("ROLLBACK"))
2179 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
2181 else if (Matches1("CALL"))
2182 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_procedures, NULL);
2183 else if (Matches2("CALL", MatchAny))
2184 COMPLETE_WITH_CONST("(");
2186 else if (Matches1("CLUSTER"))
2187 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
2188 else if (Matches2("CLUSTER", "VERBOSE"))
2189 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2190 /* If we have CLUSTER <sth>, then add "USING" */
2191 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
2192 COMPLETE_WITH_CONST("USING");
2193 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
2194 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
2195 COMPLETE_WITH_CONST("USING");
2196 /* If we have CLUSTER <sth> USING, then add the index as well */
2197 else if (Matches3("CLUSTER", MatchAny, "USING") ||
2198 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
2200 completion_info_charp = prev2_wd;
2201 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2205 else if (Matches1("COMMENT"))
2206 COMPLETE_WITH_CONST("ON");
2207 else if (Matches2("COMMENT", "ON"))
2209 static const char *const list_COMMENT[] =
2210 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
2211 "EVENT TRIGGER", "EXTENSION",
2212 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2213 "SERVER", "INDEX", "LANGUAGE", "POLICY", "PUBLICATION", "RULE",
2214 "SCHEMA", "SEQUENCE", "STATISTICS", "SUBSCRIPTION",
2215 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
2216 "PROCEDURE", "ROUTINE",
2217 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
2218 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
2220 COMPLETE_WITH_LIST(list_COMMENT);
2222 else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
2223 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2224 else if (Matches3("COMMENT", "ON", "FOREIGN"))
2225 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2226 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
2227 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2228 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
2229 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
2230 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
2231 COMPLETE_WITH_CONST("ON");
2232 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2234 completion_info_charp = prev2_wd;
2235 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
2237 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
2238 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2239 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
2240 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2241 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
2242 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2243 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
2244 COMPLETE_WITH_CONST("IS");
2249 * If we have COPY, offer list of tables or "(" (Also cover the analogous
2250 * backslash command).
2252 else if (Matches1("COPY|\\copy"))
2253 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2254 " UNION ALL SELECT '('");
2255 /* If we have COPY BINARY, complete with list of tables */
2256 else if (Matches2("COPY", "BINARY"))
2257 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2258 /* If we have COPY (, complete it with legal commands */
2259 else if (Matches2("COPY|\\copy", "("))
2260 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
2261 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
2262 else if (Matches2("COPY|\\copy", MatchAny) ||
2263 Matches3("COPY", "BINARY", MatchAny))
2264 COMPLETE_WITH_LIST2("FROM", "TO");
2265 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
2266 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
2267 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
2269 completion_charp = "";
2270 matches = completion_matches(text, complete_from_files);
2273 /* Handle COPY [BINARY] <sth> FROM|TO filename */
2274 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
2275 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
2276 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
2279 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
2280 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
2281 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
2282 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
2285 /* CREATE ACCESS METHOD */
2286 /* Complete "CREATE ACCESS METHOD <name>" */
2287 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
2288 COMPLETE_WITH_CONST("TYPE");
2289 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
2290 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
2291 COMPLETE_WITH_CONST("INDEX");
2292 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
2293 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
2294 COMPLETE_WITH_CONST("HANDLER");
2296 /* CREATE DATABASE */
2297 else if (Matches3("CREATE", "DATABASE", MatchAny))
2298 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2300 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2301 "LC_COLLATE", "LC_CTYPE");
2303 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2304 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2306 /* CREATE EXTENSION */
2307 /* Complete with available extensions rather than installed ones. */
2308 else if (Matches2("CREATE", "EXTENSION"))
2309 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2310 /* CREATE EXTENSION <name> */
2311 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2312 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2313 /* CREATE EXTENSION <name> VERSION */
2314 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2316 completion_info_charp = prev2_wd;
2317 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2320 /* CREATE FOREIGN */
2321 else if (Matches2("CREATE", "FOREIGN"))
2322 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2324 /* CREATE FOREIGN DATA WRAPPER */
2325 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2326 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2328 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2329 /* First off we complete CREATE UNIQUE with "INDEX" */
2330 else if (TailMatches2("CREATE", "UNIQUE"))
2331 COMPLETE_WITH_CONST("INDEX");
2334 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2337 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2338 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2339 " UNION SELECT 'ON'"
2340 " UNION SELECT 'CONCURRENTLY'");
2341 /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
2342 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2343 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2344 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2347 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2350 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2351 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2352 " UNION SELECT 'ON'");
2353 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2354 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2355 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2356 COMPLETE_WITH_CONST("ON");
2359 * Complete INDEX <name> ON <table> with a list of table columns (which
2360 * should really be in parens)
2362 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2363 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2364 COMPLETE_WITH_LIST2("(", "USING");
2365 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2366 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2367 COMPLETE_WITH_ATTR(prev2_wd, "");
2368 /* same if you put in USING */
2369 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2370 COMPLETE_WITH_ATTR(prev4_wd, "");
2371 /* Complete USING with an index method */
2372 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2373 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2374 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2375 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2376 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2377 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2378 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2379 COMPLETE_WITH_CONST("(");
2382 /* Complete "CREATE POLICY <name> ON" */
2383 else if (Matches3("CREATE", "POLICY", MatchAny))
2384 COMPLETE_WITH_CONST("ON");
2385 /* Complete "CREATE POLICY <name> ON <table>" */
2386 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2387 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2388 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
2389 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2390 COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
2391 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
2392 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
2393 COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
2396 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2397 * FOR|TO|USING|WITH CHECK
2399 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
2400 COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
2401 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2402 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2403 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2404 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2405 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2406 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2407 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2408 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2409 COMPLETE_WITH_LIST2("TO", "USING (");
2410 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2411 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2412 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2413 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2414 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2415 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2416 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2417 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2418 COMPLETE_WITH_CONST("(");
2421 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2422 * ALL|SELECT|INSERT|UPDATE|DELETE
2424 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
2425 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2428 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2429 * INSERT TO|WITH CHECK"
2431 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
2432 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2435 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2436 * SELECT|DELETE TO|USING"
2438 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
2439 COMPLETE_WITH_LIST2("TO", "USING (");
2442 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2443 * ALL|UPDATE TO|USING|WITH CHECK
2445 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
2446 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2449 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
2452 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
2453 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2456 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2459 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
2460 COMPLETE_WITH_CONST("(");
2463 /* CREATE PUBLICATION */
2464 else if (Matches3("CREATE", "PUBLICATION", MatchAny))
2465 COMPLETE_WITH_LIST3("FOR TABLE", "FOR ALL TABLES", "WITH (");
2466 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR"))
2467 COMPLETE_WITH_LIST2("TABLE", "ALL TABLES");
2468 /* Complete "CREATE PUBLICATION <name> FOR TABLE <table>" */
2469 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
2470 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2471 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
2472 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
2473 COMPLETE_WITH_CONST("publish");
2476 /* Complete "CREATE RULE <sth>" with "AS ON" */
2477 else if (Matches3("CREATE", "RULE", MatchAny))
2478 COMPLETE_WITH_CONST("AS ON");
2479 /* Complete "CREATE RULE <sth> AS" with "ON" */
2480 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2481 COMPLETE_WITH_CONST("ON");
2482 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2483 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2484 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2485 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2486 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2487 COMPLETE_WITH_CONST("TO");
2488 /* Complete "AS ON <sth> TO" with a table name */
2489 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2490 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2492 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2493 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2494 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2495 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2496 "CYCLE", "OWNED BY", "START WITH");
2497 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2498 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2499 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2501 /* CREATE SERVER <name> */
2502 else if (Matches3("CREATE", "SERVER", MatchAny))
2503 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2505 /* CREATE STATISTICS <name> */
2506 else if (Matches3("CREATE", "STATISTICS", MatchAny))
2507 COMPLETE_WITH_LIST2("(", "ON");
2508 else if (Matches4("CREATE", "STATISTICS", MatchAny, "("))
2509 COMPLETE_WITH_LIST2("ndistinct", "dependencies");
2510 else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
2511 previous_words[0][0] == '(' &&
2512 previous_words[0][strlen(previous_words[0]) - 1] == ')')
2513 COMPLETE_WITH_CONST("ON");
2514 else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
2515 TailMatches1("FROM"))
2516 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2518 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2519 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2520 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2521 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2522 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2523 else if (TailMatches2("CREATE", "UNLOGGED"))
2524 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2525 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
2526 else if (TailMatches2("PARTITION", "BY"))
2527 COMPLETE_WITH_LIST2("RANGE (", "LIST (");
2528 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
2529 else if (TailMatches2("PARTITION", "OF"))
2530 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables, "");
2531 /* Limited completion support for partition bound specification */
2532 else if (TailMatches3("PARTITION", "OF", MatchAny))
2533 COMPLETE_WITH_LIST2("FOR VALUES", "DEFAULT");
2535 /* CREATE TABLESPACE */
2536 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2537 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2538 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2539 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2540 COMPLETE_WITH_CONST("LOCATION");
2542 /* CREATE TEXT SEARCH */
2543 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2544 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2545 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2546 COMPLETE_WITH_CONST("(");
2548 /* CREATE SUBSCRIPTION */
2549 else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
2550 COMPLETE_WITH_CONST("CONNECTION");
2551 else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
2552 COMPLETE_WITH_CONST("PUBLICATION");
2553 else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
2554 MatchAny, "PUBLICATION"))
2556 /* complete with nothing here as this refers to remote publications */
2558 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("PUBLICATION", MatchAny))
2559 COMPLETE_WITH_CONST("WITH (");
2560 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
2561 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
2562 COMPLETE_WITH_LIST6("copy_data", "connect", "create_slot", "enabled",
2563 "slot_name", "synchronous_commit");
2565 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2566 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2567 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2568 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2569 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2570 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2571 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2572 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2573 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2574 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2575 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2576 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2577 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2578 COMPLETE_WITH_LIST2("ON", "OR");
2581 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2584 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2585 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2586 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2587 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2588 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2589 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
2590 COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
2591 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2592 else if (HeadMatches2("CREATE", "TRIGGER") &&
2593 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
2594 COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2595 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
2596 COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
2597 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
2598 COMPLETE_WITH_CONST("AS");
2599 else if (HeadMatches2("CREATE", "TRIGGER") &&
2600 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
2601 TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
2602 COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2603 else if (HeadMatches2("CREATE", "TRIGGER") &&
2604 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
2605 TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
2606 COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2607 else if (HeadMatches2("CREATE", "TRIGGER") &&
2608 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2609 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2610 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
2611 TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
2612 COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
2613 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
2614 COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
2615 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
2616 COMPLETE_WITH_LIST2("ROW", "STATEMENT");
2617 else if (HeadMatches2("CREATE", "TRIGGER") &&
2618 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
2619 TailMatches2("FOR", "ROW|STATEMENT")))
2620 COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
2621 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2622 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2623 COMPLETE_WITH_CONST("PROCEDURE");
2624 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
2625 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2627 /* CREATE ROLE,USER,GROUP <name> */
2628 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2629 !TailMatches2("USER", "MAPPING"))
2631 static const char *const list_CREATEROLE[] =
2632 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2633 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2634 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2635 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2636 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2637 "VALID UNTIL", "WITH", NULL};
2639 COMPLETE_WITH_LIST(list_CREATEROLE);
2642 /* CREATE ROLE,USER,GROUP <name> WITH */
2643 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2645 /* Similar to the above, but don't complete "WITH" again. */
2646 static const char *const list_CREATEROLE_WITH[] =
2647 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2648 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2649 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2650 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2651 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2652 "VALID UNTIL", NULL};
2654 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2657 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2658 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2659 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2661 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2662 /* Complete CREATE VIEW <name> with AS */
2663 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2664 COMPLETE_WITH_CONST("AS");
2665 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2666 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2667 COMPLETE_WITH_CONST("SELECT");
2669 /* CREATE MATERIALIZED VIEW */
2670 else if (Matches2("CREATE", "MATERIALIZED"))
2671 COMPLETE_WITH_CONST("VIEW");
2672 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2673 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2674 COMPLETE_WITH_CONST("AS");
2675 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2676 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2677 COMPLETE_WITH_CONST("SELECT");
2679 /* CREATE EVENT TRIGGER */
2680 else if (Matches2("CREATE", "EVENT"))
2681 COMPLETE_WITH_CONST("TRIGGER");
2682 /* Complete CREATE EVENT TRIGGER <name> with ON */
2683 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2684 COMPLETE_WITH_CONST("ON");
2685 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2686 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2687 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2690 else if (Matches1("DEALLOCATE"))
2691 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2694 else if (Matches2("DECLARE", MatchAny))
2695 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2697 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2698 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2700 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2701 /* ... despite which, only complete DELETE with FROM at start of line */
2702 else if (Matches1("DELETE"))
2703 COMPLETE_WITH_CONST("FROM");
2704 /* Complete DELETE FROM with a list of tables */
2705 else if (TailMatches2("DELETE", "FROM"))
2706 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2707 /* Complete DELETE FROM <table> */
2708 else if (TailMatches3("DELETE", "FROM", MatchAny))
2709 COMPLETE_WITH_LIST2("USING", "WHERE");
2710 /* XXX: implement tab completion for DELETE ... USING */
2713 else if (Matches1("DISCARD"))
2714 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2717 else if (Matches1("DO"))
2718 COMPLETE_WITH_CONST("LANGUAGE");
2721 /* Complete DROP object with CASCADE / RESTRICT */
2722 else if (Matches3("DROP",
2723 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
2725 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2726 (Matches4("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
2727 ends_with(prev_wd, ')')) ||
2728 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2729 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2730 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2731 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2732 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2734 /* help completing some of the variants */
2735 else if (Matches3("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
2736 COMPLETE_WITH_CONST("(");
2737 else if (Matches4("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
2738 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2739 else if (Matches2("DROP", "FOREIGN"))
2740 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2743 else if (Matches2("DROP", "INDEX"))
2744 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2745 " UNION SELECT 'CONCURRENTLY'");
2746 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2747 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2748 else if (Matches3("DROP", "INDEX", MatchAny))
2749 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2750 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2751 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2753 /* DROP MATERIALIZED VIEW */
2754 else if (Matches2("DROP", "MATERIALIZED"))
2755 COMPLETE_WITH_CONST("VIEW");
2756 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2757 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2760 else if (Matches2("DROP", "OWNED"))
2761 COMPLETE_WITH_CONST("BY");
2762 else if (Matches3("DROP", "OWNED", "BY"))
2763 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2765 /* DROP TEXT SEARCH */
2766 else if (Matches3("DROP", "TEXT", "SEARCH"))
2767 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2770 else if (Matches3("DROP", "TRIGGER", MatchAny))
2771 COMPLETE_WITH_CONST("ON");
2772 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2774 completion_info_charp = prev2_wd;
2775 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2777 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2778 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2780 /* DROP ACCESS METHOD */
2781 else if (Matches2("DROP", "ACCESS"))
2782 COMPLETE_WITH_CONST("METHOD");
2783 else if (Matches3("DROP", "ACCESS", "METHOD"))
2784 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2786 /* DROP EVENT TRIGGER */
2787 else if (Matches2("DROP", "EVENT"))
2788 COMPLETE_WITH_CONST("TRIGGER");
2789 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2790 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2792 /* DROP POLICY <name> */
2793 else if (Matches2("DROP", "POLICY"))
2794 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2795 /* DROP POLICY <name> ON */
2796 else if (Matches3("DROP", "POLICY", MatchAny))
2797 COMPLETE_WITH_CONST("ON");
2798 /* DROP POLICY <name> ON <table> */
2799 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2801 completion_info_charp = prev2_wd;
2802 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2806 else if (Matches3("DROP", "RULE", MatchAny))
2807 COMPLETE_WITH_CONST("ON");
2808 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2810 completion_info_charp = prev2_wd;
2811 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2813 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2814 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2817 else if (Matches1("EXECUTE"))
2818 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2823 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2825 else if (Matches1("EXPLAIN"))
2826 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2827 "ANALYZE", "VERBOSE");
2828 else if (Matches2("EXPLAIN", "ANALYZE"))
2829 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2831 else if (Matches2("EXPLAIN", "VERBOSE") ||
2832 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2833 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2836 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2837 else if (Matches1("FETCH|MOVE"))
2838 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2839 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2840 else if (Matches2("FETCH|MOVE", MatchAny))
2841 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2844 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2845 * but we may as well tab-complete both: perhaps some users prefer one
2846 * variant or the other.
2848 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2849 COMPLETE_WITH_LIST2("FROM", "IN");
2851 /* FOREIGN DATA WRAPPER */
2852 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2853 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2854 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2855 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2856 /* applies in CREATE SERVER */
2857 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2858 HeadMatches2("CREATE", "SERVER"))
2859 COMPLETE_WITH_CONST("OPTIONS");
2862 else if (TailMatches2("FOREIGN", "TABLE") &&
2863 !TailMatches3("CREATE", MatchAny, MatchAny))
2864 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2866 /* FOREIGN SERVER */
2867 else if (TailMatches2("FOREIGN", "SERVER"))
2868 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2871 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
2872 * ALTER DEFAULT PRIVILEGES, so use TailMatches
2874 /* Complete GRANT/REVOKE with a list of roles and privileges */
2875 else if (TailMatches1("GRANT|REVOKE"))
2878 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
2879 * privileges (can't grant roles)
2881 if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
2882 COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
2883 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
2884 "EXECUTE", "USAGE", "ALL");
2886 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2887 " UNION SELECT 'SELECT'"
2888 " UNION SELECT 'INSERT'"
2889 " UNION SELECT 'UPDATE'"
2890 " UNION SELECT 'DELETE'"
2891 " UNION SELECT 'TRUNCATE'"
2892 " UNION SELECT 'REFERENCES'"
2893 " UNION SELECT 'TRIGGER'"
2894 " UNION SELECT 'CREATE'"
2895 " UNION SELECT 'CONNECT'"
2896 " UNION SELECT 'TEMPORARY'"
2897 " UNION SELECT 'EXECUTE'"
2898 " UNION SELECT 'USAGE'"
2899 " UNION SELECT 'ALL'");
2903 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2906 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2908 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2909 COMPLETE_WITH_CONST("ON");
2910 else if (TailMatches2("GRANT", MatchAny))
2911 COMPLETE_WITH_CONST("TO");
2913 COMPLETE_WITH_CONST("FROM");
2917 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2920 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2921 * result via UNION; seems to work intuitively.
2923 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2924 * here will only work if the privilege list contains exactly one
2927 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2930 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
2931 * objects supported.
2933 if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
2934 COMPLETE_WITH_LIST7("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS");
2936 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2937 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2938 " UNION SELECT 'ALL PROCEDURES IN SCHEMA'"
2939 " UNION SELECT 'ALL ROUTINES IN SCHEMA'"
2940 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2941 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2942 " UNION SELECT 'DATABASE'"
2943 " UNION SELECT 'DOMAIN'"
2944 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2945 " UNION SELECT 'FOREIGN SERVER'"
2946 " UNION SELECT 'FUNCTION'"
2947 " UNION SELECT 'LANGUAGE'"
2948 " UNION SELECT 'LARGE OBJECT'"
2949 " UNION SELECT 'PROCEDURE'"
2950 " UNION SELECT 'ROUTINE'"
2951 " UNION SELECT 'SCHEMA'"
2952 " UNION SELECT 'SEQUENCE'"
2953 " UNION SELECT 'TABLE'"
2954 " UNION SELECT 'TABLESPACE'"
2955 " UNION SELECT 'TYPE'");
2957 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2958 COMPLETE_WITH_LIST5("FUNCTIONS IN SCHEMA",
2959 "PROCEDURES IN SCHEMA",
2960 "ROUTINES IN SCHEMA",
2961 "SEQUENCES IN SCHEMA",
2962 "TABLES IN SCHEMA");
2963 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2964 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2967 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2968 * appropriate objects.
2970 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2972 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2974 if (TailMatches1("DATABASE"))
2975 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2976 else if (TailMatches1("DOMAIN"))
2977 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2978 else if (TailMatches1("FUNCTION"))
2979 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2980 else if (TailMatches1("LANGUAGE"))
2981 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2982 else if (TailMatches1("PROCEDURE"))
2983 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_procedures, NULL);
2984 else if (TailMatches1("ROUTINE"))
2985 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
2986 else if (TailMatches1("SCHEMA"))
2987 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2988 else if (TailMatches1("SEQUENCE"))
2989 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2990 else if (TailMatches1("TABLE"))
2991 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2992 else if (TailMatches1("TABLESPACE"))
2993 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2994 else if (TailMatches1("TYPE"))
2995 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2996 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2997 COMPLETE_WITH_CONST("TO");
2999 COMPLETE_WITH_CONST("FROM");
3003 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
3004 * CURRENT_USER, or SESSION_USER.
3006 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
3007 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
3008 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
3009 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
3010 else if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
3011 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
3012 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
3013 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
3014 COMPLETE_WITH_CONST("TO");
3015 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
3016 COMPLETE_WITH_CONST("FROM");
3018 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
3019 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
3021 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3022 COMPLETE_WITH_CONST("TO");
3024 COMPLETE_WITH_CONST("FROM");
3027 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
3028 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
3030 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3031 COMPLETE_WITH_CONST("TO");
3033 COMPLETE_WITH_CONST("FROM");
3036 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
3037 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
3039 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3040 COMPLETE_WITH_CONST("TO");
3042 COMPLETE_WITH_CONST("FROM");
3046 else if (TailMatches3("FROM", MatchAny, "GROUP"))
3047 COMPLETE_WITH_CONST("BY");
3049 /* IMPORT FOREIGN SCHEMA */
3050 else if (Matches1("IMPORT"))
3051 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
3052 else if (Matches2("IMPORT", "FOREIGN"))
3053 COMPLETE_WITH_CONST("SCHEMA");
3055 /* INSERT --- can be inside EXPLAIN, RULE, etc */
3056 /* Complete INSERT with "INTO" */
3057 else if (TailMatches1("INSERT"))
3058 COMPLETE_WITH_CONST("INTO");
3059 /* Complete INSERT INTO with table names */
3060 else if (TailMatches2("INSERT", "INTO"))
3061 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3062 /* Complete "INSERT INTO <table> (" with attribute names */
3063 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
3064 COMPLETE_WITH_ATTR(prev2_wd, "");
3067 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
3068 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
3070 else if (TailMatches3("INSERT", "INTO", MatchAny))
3071 COMPLETE_WITH_LIST6("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
3074 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
3075 * "TABLE" or "OVERRIDING"
3077 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
3078 ends_with(prev_wd, ')'))
3079 COMPLETE_WITH_LIST4("SELECT", "TABLE", "VALUES", "OVERRIDING");
3081 /* Complete OVERRIDING */
3082 else if (TailMatches1("OVERRIDING"))
3083 COMPLETE_WITH_LIST2("SYSTEM VALUE", "USER VALUE");
3085 /* Complete after OVERRIDING clause */
3086 else if (TailMatches3("OVERRIDING", MatchAny, "VALUE"))
3087 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
3089 /* Insert an open parenthesis after "VALUES" */
3090 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
3091 COMPLETE_WITH_CONST("(");
3094 /* Complete LOCK [TABLE] with a list of tables */
3095 else if (Matches1("LOCK"))
3096 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
3097 " UNION SELECT 'TABLE'");
3098 else if (Matches2("LOCK", "TABLE"))
3099 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
3101 /* For the following, handle the case of a single table only for now */
3103 /* Complete LOCK [TABLE] <table> with "IN" */
3104 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
3105 Matches3("LOCK", "TABLE", MatchAny))
3106 COMPLETE_WITH_CONST("IN");
3108 /* Complete LOCK [TABLE] <table> IN with a lock mode */
3109 else if (Matches3("LOCK", MatchAny, "IN") ||
3110 Matches4("LOCK", "TABLE", MatchAny, "IN"))
3111 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
3112 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
3113 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
3114 "SHARE ROW EXCLUSIVE MODE",
3115 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
3117 /* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
3118 else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
3119 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
3120 COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
3122 /* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
3123 else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
3124 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
3125 COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
3126 "UPDATE EXCLUSIVE MODE");
3128 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
3129 else if (TailMatches1("NOTIFY"))
3130 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'");
3133 else if (TailMatches1("OPTIONS"))
3134 COMPLETE_WITH_CONST("(");
3136 /* OWNER TO - complete with available roles */
3137 else if (TailMatches2("OWNER", "TO"))
3138 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3141 else if (TailMatches3("FROM", MatchAny, "ORDER"))
3142 COMPLETE_WITH_CONST("BY");
3143 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
3144 COMPLETE_WITH_ATTR(prev3_wd, "");
3147 else if (Matches3("PREPARE", MatchAny, "AS"))
3148 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
3151 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
3152 * managers, not for manual use in interactive sessions.
3155 /* REASSIGN OWNED BY xxx TO yyy */
3156 else if (Matches1("REASSIGN"))
3157 COMPLETE_WITH_CONST("OWNED BY");
3158 else if (Matches2("REASSIGN", "OWNED"))
3159 COMPLETE_WITH_CONST("BY");
3160 else if (Matches3("REASSIGN", "OWNED", "BY"))
3161 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3162 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
3163 COMPLETE_WITH_CONST("TO");
3164 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
3165 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3167 /* REFRESH MATERIALIZED VIEW */
3168 else if (Matches1("REFRESH"))
3169 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
3170 else if (Matches2("REFRESH", "MATERIALIZED"))
3171 COMPLETE_WITH_CONST("VIEW");
3172 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
3173 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
3174 " UNION SELECT 'CONCURRENTLY'");
3175 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
3176 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3177 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
3178 COMPLETE_WITH_CONST("WITH");
3179 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
3180 COMPLETE_WITH_CONST("WITH");
3181 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
3182 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3183 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
3184 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3185 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
3186 COMPLETE_WITH_CONST("DATA");
3187 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
3188 COMPLETE_WITH_CONST("DATA");
3191 else if (Matches1("REINDEX"))
3192 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
3193 else if (Matches2("REINDEX", "TABLE"))
3194 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3195 else if (Matches2("REINDEX", "INDEX"))
3196 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3197 else if (Matches2("REINDEX", "SCHEMA"))
3198 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3199 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
3200 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3202 /* SECURITY LABEL */
3203 else if (Matches1("SECURITY"))
3204 COMPLETE_WITH_CONST("LABEL");
3205 else if (Matches2("SECURITY", "LABEL"))
3206 COMPLETE_WITH_LIST2("ON", "FOR");
3207 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
3208 COMPLETE_WITH_CONST("ON");
3209 else if (Matches3("SECURITY", "LABEL", "ON") ||
3210 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
3212 static const char *const list_SECURITY_LABEL[] =
3213 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
3214 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
3215 "MATERIALIZED VIEW", "LANGUAGE", "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
3216 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW", NULL};
3218 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
3220 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
3221 COMPLETE_WITH_CONST("IS");
3226 /* SET, RESET, SHOW */
3227 /* Complete with a variable name */
3228 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
3229 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
3230 else if (Matches1("SHOW"))
3231 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
3232 /* Complete "SET TRANSACTION" */
3233 else if (Matches2("SET", "TRANSACTION"))
3234 COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3235 else if (Matches2("BEGIN|START", "TRANSACTION") ||
3236 Matches2("BEGIN", "WORK") ||
3237 Matches1("BEGIN") ||
3238 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
3239 COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3240 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
3241 Matches2("BEGIN", "NOT") ||
3242 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
3243 COMPLETE_WITH_CONST("DEFERRABLE");
3244 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
3245 Matches2("BEGIN", "ISOLATION") ||
3246 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
3247 COMPLETE_WITH_CONST("LEVEL");
3248 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
3249 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
3250 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
3251 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
3252 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
3253 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
3254 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
3255 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
3256 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
3257 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
3258 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
3259 COMPLETE_WITH_CONST("READ");
3260 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
3261 Matches2("BEGIN", "READ") ||
3262 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
3263 COMPLETE_WITH_LIST2("ONLY", "WRITE");
3264 /* SET CONSTRAINTS */
3265 else if (Matches2("SET", "CONSTRAINTS"))
3266 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
3267 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
3268 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
3269 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
3270 /* Complete SET ROLE */
3271 else if (Matches2("SET", "ROLE"))
3272 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3273 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
3274 else if (Matches2("SET", "SESSION"))
3275 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
3276 /* Complete SET SESSION AUTHORIZATION with username */
3277 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
3278 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
3279 /* Complete RESET SESSION with AUTHORIZATION */
3280 else if (Matches2("RESET", "SESSION"))
3281 COMPLETE_WITH_CONST("AUTHORIZATION");
3282 /* Complete SET <var> with "TO" */
3283 else if (Matches2("SET", MatchAny))
3284 COMPLETE_WITH_CONST("TO");
3285 /* Complete ALTER DATABASE|FUNCTION||PROCEDURE|ROLE|ROUTINE|USER ... SET <name> */
3286 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER") &&
3287 TailMatches2("SET", MatchAny))
3288 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
3289 /* Suggest possible variable values */
3290 else if (TailMatches3("SET", MatchAny, "TO|="))
3292 /* special cased code for individual GUCs */
3293 if (TailMatches2("DateStyle", "TO|="))
3295 static const char *const my_list[] =
3296 {"ISO", "SQL", "Postgres", "German",
3297 "YMD", "DMY", "MDY",
3298 "US", "European", "NonEuropean",
3301 COMPLETE_WITH_LIST(my_list);
3303 else if (TailMatches2("search_path", "TO|="))
3304 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
3305 " AND nspname not like 'pg\\_toast%%' "
3306 " AND nspname not like 'pg\\_temp%%' "
3307 " UNION SELECT 'DEFAULT' ");
3310 /* generic, type based, GUC support */
3311 char *guctype = get_guctype(prev2_wd);
3313 if (guctype && strcmp(guctype, "enum") == 0)
3315 char querybuf[1024];
3317 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
3318 COMPLETE_WITH_QUERY(querybuf);
3320 else if (guctype && strcmp(guctype, "bool") == 0)
3321 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
3322 "1", "0", "DEFAULT");
3324 COMPLETE_WITH_CONST("DEFAULT");
3331 /* START TRANSACTION */
3332 else if (Matches1("START"))
3333 COMPLETE_WITH_CONST("TRANSACTION");
3335 /* TABLE, but not TABLE embedded in other commands */
3336 else if (Matches1("TABLE"))
3337 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3340 else if (TailMatches1("TABLESAMPLE"))
3341 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
3342 else if (TailMatches2("TABLESAMPLE", MatchAny))
3343 COMPLETE_WITH_CONST("(");
3346 else if (Matches1("TRUNCATE"))
3347 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3350 else if (Matches1("UNLISTEN"))
3351 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 '*'");
3353 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
3354 /* If prev. word is UPDATE suggest a list of tables */
3355 else if (TailMatches1("UPDATE"))
3356 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3357 /* Complete UPDATE <table> with "SET" */
3358 else if (TailMatches2("UPDATE", MatchAny))
3359 COMPLETE_WITH_CONST("SET");
3360 /* Complete UPDATE <table> SET with list of attributes */
3361 else if (TailMatches3("UPDATE", MatchAny, "SET"))
3362 COMPLETE_WITH_ATTR(prev2_wd, "");
3363 /* UPDATE <table> SET <attr> = */
3364 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
3365 COMPLETE_WITH_CONST("=");
3368 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
3369 COMPLETE_WITH_CONST("FOR");
3370 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
3371 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3372 " UNION SELECT 'CURRENT_USER'"
3373 " UNION SELECT 'PUBLIC'"
3374 " UNION SELECT 'USER'");
3375 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
3376 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3377 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
3378 COMPLETE_WITH_CONST("SERVER");
3379 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
3380 COMPLETE_WITH_CONST("OPTIONS");
3383 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
3384 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
3386 else if (Matches1("VACUUM"))
3387 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3388 " UNION SELECT 'FULL'"
3389 " UNION SELECT 'FREEZE'"
3390 " UNION SELECT 'ANALYZE'"
3391 " UNION SELECT 'VERBOSE'");
3392 else if (Matches2("VACUUM", "FULL|FREEZE"))
3393 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3394 " UNION SELECT 'ANALYZE'"
3395 " UNION SELECT 'VERBOSE'");
3396 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
3397 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3398 " UNION SELECT 'VERBOSE'");
3399 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
3400 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3401 " UNION SELECT 'ANALYZE'");
3402 else if (Matches2("VACUUM", "VERBOSE"))
3403 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3404 " UNION SELECT 'ANALYZE'");
3405 else if (Matches2("VACUUM", "ANALYZE"))
3406 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3407 " UNION SELECT 'VERBOSE'");
3408 else if (HeadMatches1("VACUUM"))
3409 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3411 /* WITH [RECURSIVE] */
3414 * Only match when WITH is the first word, as WITH may appear in many
3417 else if (Matches1("WITH"))
3418 COMPLETE_WITH_CONST("RECURSIVE");
3421 /* Complete with list of tables */
3422 else if (Matches1("ANALYZE"))
3423 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
3426 /* Simple case of the word before the where being the table name */
3427 else if (TailMatches2(MatchAny, "WHERE"))
3428 COMPLETE_WITH_ATTR(prev2_wd, "");
3431 /* TODO: also include SRF ? */
3432 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
3433 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3436 else if (TailMatches1("JOIN"))
3437 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3439 /* Backslash commands */
3440 /* TODO: \dc \dd \dl */
3441 else if (TailMatchesCS1("\\?"))
3442 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
3443 else if (TailMatchesCS1("\\connect|\\c"))
3445 if (!recognized_connection_string(text))
3446 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3448 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
3450 if (!recognized_connection_string(prev_wd))
3451 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3453 else if (TailMatchesCS1("\\da*"))
3454 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
3455 else if (TailMatchesCS1("\\dA*"))
3456 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3457 else if (TailMatchesCS1("\\db*"))
3458 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3459 else if (TailMatchesCS1("\\dD*"))
3460 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3461 else if (TailMatchesCS1("\\des*"))
3462 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3463 else if (TailMatchesCS1("\\deu*"))
3464 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3465 else if (TailMatchesCS1("\\dew*"))
3466 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3467 else if (TailMatchesCS1("\\df*"))
3468 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3470 else if (TailMatchesCS1("\\dFd*"))
3471 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
3472 else if (TailMatchesCS1("\\dFp*"))
3473 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
3474 else if (TailMatchesCS1("\\dFt*"))
3475 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
3476 /* must be at end of \dF alternatives: */
3477 else if (TailMatchesCS1("\\dF*"))
3478 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
3480 else if (TailMatchesCS1("\\di*"))
3481 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3482 else if (TailMatchesCS1("\\dL*"))
3483 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3484 else if (TailMatchesCS1("\\dn*"))
3485 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3486 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
3487 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3488 else if (TailMatchesCS1("\\ds*"))
3489 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3490 else if (TailMatchesCS1("\\dt*"))
3491 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3492 else if (TailMatchesCS1("\\dT*"))
3493 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3494 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
3495 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3496 else if (TailMatchesCS1("\\dv*"))
3497 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3498 else if (TailMatchesCS1("\\dx*"))
3499 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
3500 else if (TailMatchesCS1("\\dm*"))
3501 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3502 else if (TailMatchesCS1("\\dE*"))
3503 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3504 else if (TailMatchesCS1("\\dy*"))
3505 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3507 /* must be at end of \d alternatives: */
3508 else if (TailMatchesCS1("\\d*"))
3509 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3511 else if (TailMatchesCS1("\\ef"))
3512 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3513 else if (TailMatchesCS1("\\ev"))
3514 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3516 else if (TailMatchesCS1("\\encoding"))
3517 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3518 else if (TailMatchesCS1("\\h|\\help"))
3519 COMPLETE_WITH_LIST(sql_commands);
3520 else if (TailMatchesCS2("\\h|\\help", MatchAny))
3522 if (TailMatches1("DROP"))
3523 matches = completion_matches(text, drop_command_generator);
3524 else if (TailMatches1("ALTER"))
3525 matches = completion_matches(text, alter_command_generator);
3528 * CREATE is recognized by tail match elsewhere, so doesn't need to be
3532 else if (TailMatchesCS3("\\h|\\help", MatchAny, MatchAny))
3534 if (TailMatches2("CREATE|DROP", "ACCESS"))
3535 COMPLETE_WITH_CONST("METHOD");
3536 else if (TailMatches2("ALTER", "DEFAULT"))
3537 COMPLETE_WITH_CONST("PRIVILEGES");
3538 else if (TailMatches2("CREATE|ALTER|DROP", "EVENT"))
3539 COMPLETE_WITH_CONST("TRIGGER");
3540 else if (TailMatches2("CREATE|ALTER|DROP", "FOREIGN"))
3541 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
3542 else if (TailMatches2("ALTER", "LARGE"))
3543 COMPLETE_WITH_CONST("OBJECT");
3544 else if (TailMatches2("CREATE|ALTER|DROP", "MATERIALIZED"))
3545 COMPLETE_WITH_CONST("VIEW");
3546 else if (TailMatches2("CREATE|ALTER|DROP", "TEXT"))
3547 COMPLETE_WITH_CONST("SEARCH");
3548 else if (TailMatches2("CREATE|ALTER|DROP", "USER"))
3549 COMPLETE_WITH_CONST("MAPPING FOR");
3551 else if (TailMatchesCS4("\\h|\\help", MatchAny, MatchAny, MatchAny))
3553 if (TailMatches3("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
3554 COMPLETE_WITH_CONST("WRAPPER");
3555 else if (TailMatches3("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
3556 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3557 else if (TailMatches3("CREATE|ALTER|DROP", "USER", "MAPPING"))
3558 COMPLETE_WITH_CONST("FOR");
3560 else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
3561 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3562 else if (TailMatchesCS1("\\password"))
3563 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3564 else if (TailMatchesCS1("\\pset"))
3566 static const char *const my_list[] =
3567 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3568 "footer", "format", "linestyle", "null", "numericlocale",
3569 "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3570 "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3571 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3573 COMPLETE_WITH_LIST_CS(my_list);
3575 else if (TailMatchesCS2("\\pset", MatchAny))
3577 if (TailMatchesCS1("format"))
3579 static const char *const my_list[] =
3580 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3581 "latex", "latex-longtable", "troff-ms", NULL};
3583 COMPLETE_WITH_LIST_CS(my_list);
3585 else if (TailMatchesCS1("linestyle"))
3586 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3587 else if (TailMatchesCS1("pager"))
3588 COMPLETE_WITH_LIST_CS3("on", "off", "always");
3589 else if (TailMatchesCS1("unicode_border_linestyle|"
3590 "unicode_column_linestyle|"
3591 "unicode_header_linestyle"))
3592 COMPLETE_WITH_LIST_CS2("single", "double");
3594 else if (TailMatchesCS1("\\unset"))
3595 matches = complete_from_variables(text, "", "", true);
3596 else if (TailMatchesCS1("\\set"))
3597 matches = complete_from_variables(text, "", "", false);
3598 else if (TailMatchesCS2("\\set", MatchAny))
3600 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3601 "SINGLELINE|SINGLESTEP"))
3602 COMPLETE_WITH_LIST_CS2("on", "off");
3603 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3604 COMPLETE_WITH_LIST_CS4("lower", "upper",
3605 "preserve-lower", "preserve-upper");
3606 else if (TailMatchesCS1("ECHO"))
3607 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3608 else if (TailMatchesCS1("ECHO_HIDDEN"))
3609 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3610 else if (TailMatchesCS1("HISTCONTROL"))
3611 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3612 "ignoreboth", "none");
3613 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3614 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3615 else if (TailMatchesCS1("SHOW_CONTEXT"))
3616 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3617 else if (TailMatchesCS1("VERBOSITY"))
3618 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3620 else if (TailMatchesCS1("\\sf*"))
3621 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3622 else if (TailMatchesCS1("\\sv*"))
3623 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3624 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3625 "\\ir|\\include_relative|\\o|\\out|"
3626 "\\s|\\w|\\write|\\lo_import"))
3628 completion_charp = "\\";
3629 matches = completion_matches(text, complete_from_files);
3633 * Finally, we look through the list of "things", such as TABLE, INDEX and
3634 * check if that was the previous word. If so, execute the query to get a
3641 for (i = 0; words_after_create[i].name; i++)
3643 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3645 if (words_after_create[i].query)
3646 COMPLETE_WITH_QUERY(words_after_create[i].query);
3647 else if (words_after_create[i].squery)
3648 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3656 * If we still don't have anything to match we have to fabricate some sort
3657 * of default list. If we were to just return NULL, readline automatically
3658 * attempts filename completion, and that's usually no good.
3660 if (matches == NULL)
3662 COMPLETE_WITH_CONST("");
3663 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3664 rl_completion_append_character = '\0';
3669 free(previous_words);
3672 /* Return our Grand List O' Matches */
3678 * GENERATOR FUNCTIONS
3680 * These functions do all the actual work of completing the input. They get
3681 * passed the text so far and the count how many times they have been called
3682 * so far with the same text.
3683 * If you read the above carefully, you'll see that these don't get called
3684 * directly but through the readline interface.
3685 * The return value is expected to be the full completion of the text, going
3686 * through a list each time, or NULL if there are no more matches. The string
3687 * will be free()'d by readline, so you must run it through strdup() or
3688 * something of that sort.
3692 * Common routine for create_command_generator and drop_command_generator.
3693 * Entries that have 'excluded' flags are not returned.
3696 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3698 static int list_index,
3702 /* If this is the first time for this completion, init some values */
3706 string_length = strlen(text);
3709 /* find something that matches */
3710 while ((name = words_after_create[list_index++].name))
3712 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3713 !(words_after_create[list_index - 1].flags & excluded))
3714 return pg_strdup_keyword_case(name, text);
3716 /* if nothing matches, return NULL */
3721 * This one gives you one from a list of things you can put after CREATE
3725 create_command_generator(const char *text, int state)
3727 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3731 * This function gives you a list of things you can put after a DROP command.
3734 drop_command_generator(const char *text, int state)
3736 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3740 * This function gives you a list of things you can put after an ALTER command.
3743 alter_command_generator(const char *text, int state)
3745 return create_or_drop_command_generator(text, state, THING_NO_ALTER);
3748 /* The following two functions are wrappers for _complete_from_query */
3751 complete_from_query(const char *text, int state)
3753 return _complete_from_query(0, text, state);
3757 complete_from_schema_query(const char *text, int state)
3759 return _complete_from_query(1, text, state);
3764 * This creates a list of matching things, according to a query pointed to
3765 * by completion_charp.
3766 * The query can be one of two kinds:
3768 * 1. A simple query which must contain a %d and a %s, which will be replaced
3769 * by the string length of the text and the text itself. The query may also
3770 * have up to four more %s in it; the first two such will be replaced by the
3771 * value of completion_info_charp, the next two by the value of
3772 * completion_info_charp2.
3774 * 2. A schema query used for completion of both schema and relation names.
3775 * These are more complex and must contain in the following order:
3776 * %d %s %d %s %d %s %s %d %s
3777 * where %d is the string length of the text and %s the text itself.
3779 * It is assumed that strings should be escaped to become SQL literals
3780 * (that is, what is in the query is actually ... '%s' ...)
3782 * See top of file for examples of both kinds of query.
3785 _complete_from_query(int is_schema_query, const char *text, int state)
3787 static int list_index,
3789 static PGresult *result = NULL;
3792 * If this is the first time for this completion, we fetch a list of our
3793 * "things" from the backend.
3797 PQExpBufferData query_buffer;
3800 char *e_info_charp2;
3801 const char *pstr = text;
3802 int char_length = 0;
3805 byte_length = strlen(text);
3808 * Count length as number of characters (not bytes), for passing to
3814 pstr += PQmblen(pstr, pset.encoding);
3817 /* Free any prior result */
3821 /* Set up suitably-escaped copies of textual inputs */
3822 e_text = escape_string(text);
3824 if (completion_info_charp)
3825 e_info_charp = escape_string(completion_info_charp);
3827 e_info_charp = NULL;
3829 if (completion_info_charp2)
3830 e_info_charp2 = escape_string(completion_info_charp2);
3832 e_info_charp2 = NULL;
3834 initPQExpBuffer(&query_buffer);
3836 if (is_schema_query)
3838 /* completion_squery gives us the pieces to assemble */
3839 const char *qualresult = completion_squery->qualresult;
3841 if (qualresult == NULL)
3842 qualresult = completion_squery->result;
3844 /* Get unqualified names matching the input-so-far */
3845 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3846 completion_squery->result,
3847 completion_squery->catname);
3848 if (completion_squery->selcondition)
3849 appendPQExpBuffer(&query_buffer, "%s AND ",
3850 completion_squery->selcondition);
3851 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3852 completion_squery->result,
3853 char_length, e_text);
3854 appendPQExpBuffer(&query_buffer, " AND %s",
3855 completion_squery->viscondition);
3858 * When fetching relation names, suppress system catalogs unless
3859 * the input-so-far begins with "pg_". This is a compromise
3860 * between not offering system catalogs for completion at all, and
3861 * having them swamp the result when the input is just "p".
3863 if (strcmp(completion_squery->catname,
3864 "pg_catalog.pg_class c") == 0 &&
3865 strncmp(text, "pg_", 3) !=0)
3867 appendPQExpBufferStr(&query_buffer,
3868 " AND c.relnamespace <> (SELECT oid FROM"
3869 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3873 * Add in matching schema names, but only if there is more than
3874 * one potential match among schema names.
3876 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3877 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3878 "FROM pg_catalog.pg_namespace n "
3879 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3880 char_length, e_text);
3881 appendPQExpBuffer(&query_buffer,
3882 " AND (SELECT pg_catalog.count(*)"
3883 " FROM pg_catalog.pg_namespace"
3884 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3885 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3886 char_length, e_text);
3889 * Add in matching qualified names, but only if there is exactly
3890 * one schema matching the input-so-far.
3892 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3893 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3894 "FROM %s, pg_catalog.pg_namespace n "
3895 "WHERE %s = n.oid AND ",
3897 completion_squery->catname,
3898 completion_squery->namespace);
3899 if (completion_squery->selcondition)
3900 appendPQExpBuffer(&query_buffer, "%s AND ",
3901 completion_squery->selcondition);
3902 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3904 char_length, e_text);
3907 * This condition exploits the single-matching-schema rule to
3908 * speed up the query
3910 appendPQExpBuffer(&query_buffer,
3911 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3912 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3913 char_length, e_text);
3914 appendPQExpBuffer(&query_buffer,
3915 " AND (SELECT pg_catalog.count(*)"
3916 " FROM pg_catalog.pg_namespace"
3917 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3918 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3919 char_length, e_text);
3921 /* If an addon query was provided, use it */
3922 if (completion_charp)
3923 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3927 /* completion_charp is an sprintf-style format string */
3928 appendPQExpBuffer(&query_buffer, completion_charp,
3929 char_length, e_text,
3930 e_info_charp, e_info_charp,
3931 e_info_charp2, e_info_charp2);
3934 /* Limit the number of records in the result */
3935 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3936 completion_max_records);
3938 result = exec_query(query_buffer.data);
3940 termPQExpBuffer(&query_buffer);
3945 free(e_info_charp2);
3948 /* Find something that matches */
3949 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3953 while (list_index < PQntuples(result) &&
3954 (item = PQgetvalue(result, list_index++, 0)))
3955 if (pg_strncasecmp(text, item, byte_length) == 0)
3956 return pg_strdup(item);
3959 /* If nothing matches, free the db structure and return null */
3967 * This function returns in order one of a fixed, NULL pointer terminated list
3968 * of strings (if matching). This can be used if there are only a fixed number
3969 * SQL words that can appear at certain spot.
3972 complete_from_list(const char *text, int state)
3974 static int string_length,
3977 static bool casesensitive;
3980 /* need to have a list */
3981 Assert(completion_charpp != NULL);
3983 /* Initialization */
3987 string_length = strlen(text);
3988 casesensitive = completion_case_sensitive;
3992 while ((item = completion_charpp[list_index++]))
3994 /* First pass is case sensitive */
3995 if (casesensitive && strncmp(text, item, string_length) == 0)
3998 return pg_strdup(item);
4001 /* Second pass is case insensitive, don't bother counting matches */
4002 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
4004 if (completion_case_sensitive)
4005 return pg_strdup(item);
4009 * If case insensitive matching was requested initially,
4010 * adjust the case according to setting.
4012 return pg_strdup_keyword_case(item, text);
4017 * No matches found. If we're not case insensitive already, lets switch to
4018 * being case insensitive and try again
4020 if (casesensitive && matches == 0)
4022 casesensitive = false;
4025 return complete_from_list(text, state);
4028 /* If no more matches, return null. */
4034 * This function returns one fixed string the first time even if it doesn't
4035 * match what's there, and nothing the second time. This should be used if
4036 * there is only one possibility that can appear at a certain spot, so
4037 * misspellings will be overwritten. The string to be passed must be in
4041 complete_from_const(const char *text, int state)
4043 Assert(completion_charp != NULL);
4046 if (completion_case_sensitive)
4047 return pg_strdup(completion_charp);
4051 * If case insensitive matching was requested initially, adjust
4052 * the case according to setting.
4054 return pg_strdup_keyword_case(completion_charp, text);
4062 * This function appends the variable name with prefix and suffix to
4063 * the variable names array.
4066 append_variable_names(char ***varnames, int *nvars,
4067 int *maxvars, const char *varname,
4068 const char *prefix, const char *suffix)
4070 if (*nvars >= *maxvars)
4073 *varnames = (char **) pg_realloc(*varnames,
4074 ((*maxvars) + 1) * sizeof(char *));
4077 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
4082 * This function supports completion with the name of a psql variable.
4083 * The variable names can be prefixed and suffixed with additional text
4084 * to support quoting usages. If need_value is true, only variables
4085 * that are currently set are included; otherwise, special variables
4086 * (those that have hooks) are included even if currently unset.
4089 complete_from_variables(const char *text, const char *prefix, const char *suffix,
4097 struct _variable *ptr;
4099 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
4101 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
4103 if (need_value && !(ptr->value))
4105 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
4109 varnames[nvars] = NULL;
4110 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
4112 for (i = 0; i < nvars; i++)
4121 * This function wraps rl_filename_completion_function() to strip quotes from
4122 * the input before searching for matches and to quote any matches for which
4123 * the consuming command will require it.
4126 complete_from_files(const char *text, int state)
4128 static const char *unquoted_text;
4129 char *unquoted_match;
4134 /* Initialization: stash the unquoted input. */
4135 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
4136 false, true, pset.encoding);
4137 /* expect a NULL return for the empty string only */
4140 Assert(*text == '\0');
4141 unquoted_text = text;
4145 unquoted_match = filename_completion_function(unquoted_text, state);
4149 * Caller sets completion_charp to a zero- or one-character string
4150 * containing the escape character. This is necessary since \copy has
4151 * no escape character, but every other backslash command recognizes
4152 * "\" as an escape character. Since we have only two callers, don't
4153 * bother providing a macro to simplify this.
4155 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
4156 '\'', *completion_charp, pset.encoding);
4158 free(unquoted_match);
4160 ret = unquoted_match;
4167 /* HELPER FUNCTIONS */
4171 * Make a pg_strdup copy of s and convert the case according to
4172 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
4175 pg_strdup_keyword_case(const char *s, const char *ref)
4179 unsigned char first = ref[0];
4183 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
4184 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
4185 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
4186 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
4188 for (p = ret; *p; p++)
4189 *p = pg_tolower((unsigned char) *p);
4193 for (p = ret; *p; p++)
4194 *p = pg_toupper((unsigned char) *p);
4202 * escape_string - Escape argument for use as string literal.
4204 * The returned value has to be freed.
4207 escape_string(const char *text)
4212 text_length = strlen(text);
4214 result = pg_malloc(text_length * 2 + 1);
4215 PQescapeStringConn(pset.db, result, text, text_length, NULL);
4222 * Execute a query and report any errors. This should be the preferred way of
4223 * talking to the database in this file.
4226 exec_query(const char *query)
4230 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
4233 result = PQexec(pset.db, query);
4235 if (PQresultStatus(result) != PGRES_TUPLES_OK)
4238 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
4239 PQerrorMessage(pset.db), query);
4250 * Parse all the word(s) before point.
4252 * Returns a malloc'd array of character pointers that point into the malloc'd
4253 * data array returned to *buffer; caller must free() both of these when done.
4254 * *nwords receives the number of words found, ie, the valid length of the
4257 * Words are returned right to left, that is, previous_words[0] gets the last
4258 * word before point, previous_words[1] the next-to-last, etc.
4261 get_previous_words(int point, char **buffer, int *nwords)
4263 char **previous_words;
4266 int words_found = 0;
4270 * If we have anything in tab_completion_query_buf, paste it together with
4271 * rl_line_buffer to construct the full query. Otherwise we can just use
4272 * rl_line_buffer as the input string.
4274 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
4276 i = tab_completion_query_buf->len;
4277 buf = pg_malloc(point + i + 2);
4278 memcpy(buf, tab_completion_query_buf->data, i);
4280 memcpy(buf + i, rl_line_buffer, point);
4283 /* Readjust point to reference appropriate offset in buf */
4287 buf = rl_line_buffer;
4290 * Allocate an array of string pointers and a buffer to hold the strings
4291 * themselves. The worst case is that the line contains only
4292 * non-whitespace WORD_BREAKS characters, making each one a separate word.
4293 * This is usually much more space than we need, but it's cheaper than
4294 * doing a separate malloc() for each word.
4296 previous_words = (char **) pg_malloc(point * sizeof(char *));
4297 *buffer = outptr = (char *) pg_malloc(point * 2);
4300 * First we look for a non-word char before the current point. (This is
4301 * probably useless, if readline is on the same page as we are about what
4302 * is a word, but if so it's cheap.)
4304 for (i = point - 1; i >= 0; i--)
4306 if (strchr(WORD_BREAKS, buf[i]))
4312 * Now parse words, working backwards, until we hit start of line. The
4313 * backwards scan has some interesting but intentional properties
4314 * concerning parenthesis handling.
4320 bool inquotes = false;
4321 int parentheses = 0;
4323 /* now find the first non-space which then constitutes the end */
4325 for (i = point; i >= 0; i--)
4327 if (!isspace((unsigned char) buf[i]))
4333 /* if no end found, we're done */
4338 * Otherwise we now look for the start. The start is either the last
4339 * character before any word-break character going backwards from the
4340 * end, or it's simply character 0. We also handle open quotes and
4343 for (start = end; start > 0; start--)
4345 if (buf[start] == '"')
4346 inquotes = !inquotes;
4349 if (buf[start] == ')')
4351 else if (buf[start] == '(')
4353 if (--parentheses <= 0)
4356 else if (parentheses == 0 &&
4357 strchr(WORD_BREAKS, buf[start - 1]))
4362 /* Return the word located at start to end inclusive */
4363 previous_words[words_found++] = outptr;
4364 i = end - start + 1;
4365 memcpy(outptr, &buf[start], i);
4369 /* Continue searching */
4373 /* Release parsing input workspace, if we made one above */
4374 if (buf != rl_line_buffer)
4377 *nwords = words_found;
4378 return previous_words;
4382 * Look up the type for the GUC variable with the passed name.
4384 * Returns NULL if the variable is unknown. Otherwise the returned string,
4385 * containing the type, has to be freed.
4388 get_guctype(const char *varname)
4390 PQExpBufferData query_buffer;
4393 char *guctype = NULL;
4395 e_varname = escape_string(varname);
4397 initPQExpBuffer(&query_buffer);
4398 appendPQExpBuffer(&query_buffer,
4399 "SELECT vartype FROM pg_catalog.pg_settings "
4400 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
4403 result = exec_query(query_buffer.data);
4404 termPQExpBuffer(&query_buffer);
4407 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
4408 guctype = pg_strdup(PQgetvalue(result, 0, 0));
4418 * Surround a string with single quotes. This works for both SQL and
4419 * psql internal. Currently disabled because it is reported not to
4420 * cooperate with certain versions of readline.
4423 quote_file_name(char *text, int match_type, char *quote_pointer)
4428 (void) quote_pointer; /* not used */
4430 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
4431 s = pg_malloc(length);
4433 strcpy(s + 1, text);
4434 if (match_type == SINGLE_MATCH)
4435 s[length - 2] = '\'';
4436 s[length - 1] = '\0';
4441 dequote_file_name(char *text, char quote_char)
4447 return pg_strdup(text);
4449 length = strlen(text);
4450 s = pg_malloc(length - 2 + 1);
4451 strlcpy(s, text +1, length - 2 + 1);
4455 #endif /* NOT_USED */
4457 #endif /* USE_READLINE */