2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2018, PostgreSQL Global Development Group
6 * src/bin/psql/tab-complete.c
9 /*----------------------------------------------------------------------
10 * This file implements a somewhat more sophisticated readline "TAB
11 * completion" in psql. It is not intended to be AI, to replace
12 * learning SQL, or to relieve you from thinking about what you're
13 * doing. Also it does not always give you all the syntactically legal
14 * completions, only those that are the most common or the ones that
15 * the programmer felt most like implementing.
17 * CAVEAT: Tab completion causes queries to be sent to the backend.
18 * The number of tuples returned gets limited, in most default
19 * installations to 1000, but if you still don't like this prospect,
20 * you can turn off tab completion in your ~/.inputrc (or else
21 * ${INPUTRC}) file so:
24 * set disable-completion on
27 * See `man 3 readline' or `info readline' for the full details.
30 * - Quotes, parentheses, and other funny characters are not handled
31 * all that gracefully.
32 *----------------------------------------------------------------------
35 #include "postgres_fe.h"
36 #include "tab-complete.h"
39 /* If we don't have this, we might as well forget about the whole thing: */
44 #include "catalog/pg_class_d.h"
47 #include "pqexpbuffer.h"
50 #include "stringutils.h"
52 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
53 #define filename_completion_function rl_filename_completion_function
55 /* missing in some header files */
56 extern char *filename_completion_function();
59 #ifdef HAVE_RL_COMPLETION_MATCHES
60 #define completion_matches rl_completion_matches
63 /* word break characters */
64 #define WORD_BREAKS "\t\n@$><=;|&{() "
67 * Since readline doesn't let us pass any state through to the tab completion
68 * callback, we have to use this global variable to let get_previous_words()
69 * get at the previous lines of the current command. Ick.
71 PQExpBuffer tab_completion_query_buf = NULL;
74 * In some situations, the query to find out what names are available to
75 * complete with must vary depending on server version. We handle this by
76 * storing a list of queries, each tagged with the minimum server version
77 * it will work for. Each list must be stored in descending server version
78 * order, so that the first satisfactory query is the one to use.
80 * When the query string is otherwise constant, an array of VersionedQuery
81 * suffices. Terminate the array with an entry having min_server_version = 0.
82 * That entry's query string can be a query that works in all supported older
83 * server versions, or NULL to give up and do no completion.
85 typedef struct VersionedQuery
87 int min_server_version;
92 * This struct is used to define "schema queries", which are custom-built
93 * to obtain possibly-schema-qualified names of database objects. There is
94 * enough similarity in the structure that we don't want to repeat it each
95 * time. So we put the components of each query into this struct and
96 * assemble them with the common boilerplate in _complete_from_query().
98 * As with VersionedQuery, we can use an array of these if the query details
99 * must vary across versions.
101 typedef struct SchemaQuery
104 * If not zero, minimum server version this struct applies to. If not
105 * zero, there should be a following struct with a smaller minimum server
106 * version; use catname == NULL in the last entry if we should do nothing.
108 int min_server_version;
111 * Name of catalog or catalogs to be queried, with alias, eg.
112 * "pg_catalog.pg_class c". Note that "pg_namespace n" will be added.
117 * Selection condition --- only rows meeting this condition are candidates
118 * to display. If catname mentions multiple tables, include the necessary
119 * join condition here. For example, this might look like "c.relkind = "
120 * CppAsString2(RELKIND_RELATION). Write NULL (not an empty string) if
123 const char *selcondition;
126 * Visibility condition --- which rows are visible without schema
127 * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
129 const char *viscondition;
132 * Namespace --- name of field to join to pg_namespace.oid. For example,
135 const char *namespace;
138 * Result --- the appropriately-quoted name to return, in the case of an
139 * unqualified name. For example, "pg_catalog.quote_ident(c.relname)".
144 * In some cases a different result must be used for qualified names.
145 * Enter that here, or write NULL if result can be used.
147 const char *qualresult;
151 /* Store maximum number of records we want from database queries
152 * (implemented via SELECT ... LIMIT xx).
154 static int completion_max_records;
157 * Communication variables set by COMPLETE_WITH_FOO macros and then used by
158 * the completion callback functions. Ugly but there is no better way.
160 static const char *completion_charp; /* to pass a string */
161 static const char *const *completion_charpp; /* to pass a list of strings */
162 static const char *completion_info_charp; /* to pass a second string */
163 static const char *completion_info_charp2; /* to pass a third string */
164 static const VersionedQuery *completion_vquery; /* to pass a VersionedQuery */
165 static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
166 static bool completion_case_sensitive; /* completion is case sensitive */
169 * A few macros to ease typing. You can use these to complete the given
171 * 1) The results from a query you pass it. (Perhaps one of those below?)
172 * We support both simple and versioned queries.
173 * 2) The results from a schema query you pass it.
174 * We support both simple and versioned schema queries.
175 * 3) The items from a null-pointer-terminated list (with or without
176 * case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
177 * 4) A string constant.
178 * 5) The list of attributes of the given table (possibly schema-qualified).
179 * 6/ The list of arguments to the given function (possibly schema-qualified).
181 #define COMPLETE_WITH_QUERY(query) \
183 completion_charp = query; \
184 matches = completion_matches(text, complete_from_query); \
187 #define COMPLETE_WITH_VERSIONED_QUERY(query) \
189 completion_vquery = query; \
190 matches = completion_matches(text, complete_from_versioned_query); \
193 #define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
195 completion_squery = &(query); \
196 completion_charp = addon; \
197 matches = completion_matches(text, complete_from_schema_query); \
200 #define COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(query, addon) \
202 completion_squery = query; \
203 completion_vquery = addon; \
204 matches = completion_matches(text, complete_from_versioned_schema_query); \
207 #define COMPLETE_WITH_LIST_CS(list) \
209 completion_charpp = list; \
210 completion_case_sensitive = true; \
211 matches = completion_matches(text, complete_from_list); \
214 #define COMPLETE_WITH_LIST(list) \
216 completion_charpp = list; \
217 completion_case_sensitive = false; \
218 matches = completion_matches(text, complete_from_list); \
221 #define COMPLETE_WITH_CONST(string) \
223 completion_charp = string; \
224 completion_case_sensitive = false; \
225 matches = completion_matches(text, complete_from_const); \
228 #define COMPLETE_WITH_ATTR(relation, addon) \
230 char *_completion_schema; \
231 char *_completion_table; \
233 _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
234 false, false, pset.encoding); \
235 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
236 false, false, pset.encoding); \
237 _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
238 false, false, pset.encoding); \
239 if (_completion_table == NULL) \
241 completion_charp = Query_for_list_of_attributes addon; \
242 completion_info_charp = relation; \
246 completion_charp = Query_for_list_of_attributes_with_schema addon; \
247 completion_info_charp = _completion_table; \
248 completion_info_charp2 = _completion_schema; \
250 matches = completion_matches(text, complete_from_query); \
253 #define COMPLETE_WITH_ENUM_VALUE(type) \
255 char *_completion_schema; \
256 char *_completion_type; \
258 _completion_schema = strtokx(type, " \t\n\r", ".", "\"", 0, \
259 false, false, pset.encoding); \
260 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
261 false, false, pset.encoding); \
262 _completion_type = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
263 false, false, pset.encoding); \
264 if (_completion_type == NULL)\
266 completion_charp = Query_for_list_of_enum_values; \
267 completion_info_charp = type; \
271 completion_charp = Query_for_list_of_enum_values_with_schema; \
272 completion_info_charp = _completion_type; \
273 completion_info_charp2 = _completion_schema; \
275 matches = completion_matches(text, complete_from_query); \
278 #define COMPLETE_WITH_FUNCTION_ARG(function) \
280 char *_completion_schema; \
281 char *_completion_function; \
283 _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
284 false, false, pset.encoding); \
285 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
286 false, false, pset.encoding); \
287 _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
288 false, false, pset.encoding); \
289 if (_completion_function == NULL) \
291 completion_charp = Query_for_list_of_arguments; \
292 completion_info_charp = function; \
296 completion_charp = Query_for_list_of_arguments_with_schema; \
297 completion_info_charp = _completion_function; \
298 completion_info_charp2 = _completion_schema; \
300 matches = completion_matches(text, complete_from_query); \
304 * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
305 * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
307 #define COMPLETE_WITH_LIST2(s1, s2) \
309 static const char *const list[] = { s1, s2, NULL }; \
310 COMPLETE_WITH_LIST(list); \
313 #define COMPLETE_WITH_LIST3(s1, s2, s3) \
315 static const char *const list[] = { s1, s2, s3, NULL }; \
316 COMPLETE_WITH_LIST(list); \
319 #define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
321 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
322 COMPLETE_WITH_LIST(list); \
325 #define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
327 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
328 COMPLETE_WITH_LIST(list); \
331 #define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \
333 static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \
334 COMPLETE_WITH_LIST(list); \
337 #define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \
339 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \
340 COMPLETE_WITH_LIST(list); \
343 #define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \
345 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \
346 COMPLETE_WITH_LIST(list); \
349 #define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
351 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
352 COMPLETE_WITH_LIST(list); \
355 #define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
357 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
358 COMPLETE_WITH_LIST(list); \
362 * Likewise for COMPLETE_WITH_LIST_CS.
364 #define COMPLETE_WITH_LIST_CS2(s1, s2) \
366 static const char *const list[] = { s1, s2, NULL }; \
367 COMPLETE_WITH_LIST_CS(list); \
370 #define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
372 static const char *const list[] = { s1, s2, s3, NULL }; \
373 COMPLETE_WITH_LIST_CS(list); \
376 #define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
378 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
379 COMPLETE_WITH_LIST_CS(list); \
382 #define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
384 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
385 COMPLETE_WITH_LIST_CS(list); \
389 * Assembly instructions for schema queries
392 static const SchemaQuery Query_for_list_of_aggregates[] = {
394 /* min_server_version */
397 "pg_catalog.pg_proc p",
401 "pg_catalog.pg_function_is_visible(p.oid)",
405 "pg_catalog.quote_ident(p.proname)",
410 /* min_server_version */
413 "pg_catalog.pg_proc p",
417 "pg_catalog.pg_function_is_visible(p.oid)",
421 "pg_catalog.quote_ident(p.proname)",
427 static const SchemaQuery Query_for_list_of_datatypes = {
428 /* min_server_version */
431 "pg_catalog.pg_type t",
432 /* selcondition --- ignore table rowtypes and array types */
434 " OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
435 " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
436 "AND t.typname !~ '^_'",
438 "pg_catalog.pg_type_is_visible(t.oid)",
442 "pg_catalog.format_type(t.oid, NULL)",
444 "pg_catalog.quote_ident(t.typname)"
447 static const SchemaQuery Query_for_list_of_domains = {
448 /* min_server_version */
451 "pg_catalog.pg_type t",
455 "pg_catalog.pg_type_is_visible(t.oid)",
459 "pg_catalog.quote_ident(t.typname)",
464 /* Note: this intentionally accepts aggregates as well as plain functions */
465 static const SchemaQuery Query_for_list_of_functions[] = {
467 /* min_server_version */
470 "pg_catalog.pg_proc p",
474 "pg_catalog.pg_function_is_visible(p.oid)",
478 "pg_catalog.quote_ident(p.proname)",
483 /* min_server_version */
486 "pg_catalog.pg_proc p",
490 "pg_catalog.pg_function_is_visible(p.oid)",
494 "pg_catalog.quote_ident(p.proname)",
500 static const SchemaQuery Query_for_list_of_indexes = {
501 /* min_server_version */
504 "pg_catalog.pg_class c",
506 "c.relkind IN (" CppAsString2(RELKIND_INDEX) ", "
507 CppAsString2(RELKIND_PARTITIONED_INDEX) ")",
509 "pg_catalog.pg_table_is_visible(c.oid)",
513 "pg_catalog.quote_ident(c.relname)",
518 static const SchemaQuery Query_for_list_of_procedures[] = {
520 /* min_server_version */
523 "pg_catalog.pg_proc p",
527 "pg_catalog.pg_function_is_visible(p.oid)",
531 "pg_catalog.quote_ident(p.proname)",
538 static const SchemaQuery Query_for_list_of_routines = {
539 /* min_server_version */
542 "pg_catalog.pg_proc p",
546 "pg_catalog.pg_function_is_visible(p.oid)",
550 "pg_catalog.quote_ident(p.proname)",
555 static const SchemaQuery Query_for_list_of_sequences = {
556 /* min_server_version */
559 "pg_catalog.pg_class c",
561 "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
563 "pg_catalog.pg_table_is_visible(c.oid)",
567 "pg_catalog.quote_ident(c.relname)",
572 static const SchemaQuery Query_for_list_of_foreign_tables = {
573 /* min_server_version */
576 "pg_catalog.pg_class c",
578 "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
580 "pg_catalog.pg_table_is_visible(c.oid)",
584 "pg_catalog.quote_ident(c.relname)",
589 static const SchemaQuery Query_for_list_of_tables = {
590 /* min_server_version */
593 "pg_catalog.pg_class c",
595 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
596 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
598 "pg_catalog.pg_table_is_visible(c.oid)",
602 "pg_catalog.quote_ident(c.relname)",
607 static const SchemaQuery Query_for_list_of_partitioned_tables = {
608 /* min_server_version */
611 "pg_catalog.pg_class c",
613 "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
615 "pg_catalog.pg_table_is_visible(c.oid)",
619 "pg_catalog.quote_ident(c.relname)",
624 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
625 /* min_server_version */
628 "pg_catalog.pg_constraint c",
632 "true", /* there is no pg_constraint_is_visible */
636 "pg_catalog.quote_ident(c.conname)",
641 /* Relations supporting INSERT, UPDATE or DELETE */
642 static const SchemaQuery Query_for_list_of_updatables = {
643 /* min_server_version */
646 "pg_catalog.pg_class c",
648 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
649 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
650 CppAsString2(RELKIND_VIEW) ", "
651 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
653 "pg_catalog.pg_table_is_visible(c.oid)",
657 "pg_catalog.quote_ident(c.relname)",
662 static const SchemaQuery Query_for_list_of_relations = {
663 /* min_server_version */
666 "pg_catalog.pg_class c",
670 "pg_catalog.pg_table_is_visible(c.oid)",
674 "pg_catalog.quote_ident(c.relname)",
679 static const SchemaQuery Query_for_list_of_tsvmf = {
680 /* min_server_version */
683 "pg_catalog.pg_class c",
685 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
686 CppAsString2(RELKIND_SEQUENCE) ", "
687 CppAsString2(RELKIND_VIEW) ", "
688 CppAsString2(RELKIND_MATVIEW) ", "
689 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
690 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
692 "pg_catalog.pg_table_is_visible(c.oid)",
696 "pg_catalog.quote_ident(c.relname)",
701 static const SchemaQuery Query_for_list_of_tmf = {
702 /* min_server_version */
705 "pg_catalog.pg_class c",
707 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
708 CppAsString2(RELKIND_MATVIEW) ", "
709 CppAsString2(RELKIND_FOREIGN_TABLE) ")",
711 "pg_catalog.pg_table_is_visible(c.oid)",
715 "pg_catalog.quote_ident(c.relname)",
720 static const SchemaQuery Query_for_list_of_tpm = {
721 /* min_server_version */
724 "pg_catalog.pg_class c",
726 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
727 CppAsString2(RELKIND_PARTITIONED_TABLE) ", "
728 CppAsString2(RELKIND_MATVIEW) ")",
730 "pg_catalog.pg_table_is_visible(c.oid)",
734 "pg_catalog.quote_ident(c.relname)",
739 static const SchemaQuery Query_for_list_of_tm = {
740 /* min_server_version */
743 "pg_catalog.pg_class c",
745 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
746 CppAsString2(RELKIND_MATVIEW) ")",
748 "pg_catalog.pg_table_is_visible(c.oid)",
752 "pg_catalog.quote_ident(c.relname)",
757 static const SchemaQuery Query_for_list_of_views = {
758 /* min_server_version */
761 "pg_catalog.pg_class c",
763 "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
765 "pg_catalog.pg_table_is_visible(c.oid)",
769 "pg_catalog.quote_ident(c.relname)",
774 static const SchemaQuery Query_for_list_of_matviews = {
775 /* min_server_version */
778 "pg_catalog.pg_class c",
780 "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
782 "pg_catalog.pg_table_is_visible(c.oid)",
786 "pg_catalog.quote_ident(c.relname)",
791 static const SchemaQuery Query_for_list_of_statistics = {
792 /* min_server_version */
795 "pg_catalog.pg_statistic_ext s",
799 "pg_catalog.pg_statistics_obj_is_visible(s.oid)",
803 "pg_catalog.quote_ident(s.stxname)",
810 * Queries to get lists of names of various kinds of things, possibly
811 * restricted to names matching a partially entered name. In these queries,
812 * the first %s will be replaced by the text entered so far (suitably escaped
813 * to become a SQL literal string). %d will be replaced by the length of the
814 * string (in unescaped form). A second and third %s, if present, will be
815 * replaced by a suitably-escaped version of the string provided in
816 * completion_info_charp. A fourth and fifth %s are similarly replaced by
817 * completion_info_charp2.
819 * Beware that the allowed sequences of %s and %d are determined by
820 * _complete_from_query().
823 #define Query_for_list_of_attributes \
824 "SELECT pg_catalog.quote_ident(attname) "\
825 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
826 " WHERE c.oid = a.attrelid "\
827 " AND a.attnum > 0 "\
828 " AND NOT a.attisdropped "\
829 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
830 " AND (pg_catalog.quote_ident(relname)='%s' "\
831 " OR '\"' || relname || '\"'='%s') "\
832 " AND pg_catalog.pg_table_is_visible(c.oid)"
834 #define Query_for_list_of_attributes_with_schema \
835 "SELECT pg_catalog.quote_ident(attname) "\
836 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
837 " WHERE c.oid = a.attrelid "\
838 " AND n.oid = c.relnamespace "\
839 " AND a.attnum > 0 "\
840 " AND NOT a.attisdropped "\
841 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
842 " AND (pg_catalog.quote_ident(relname)='%s' "\
843 " OR '\"' || relname || '\"' ='%s') "\
844 " AND (pg_catalog.quote_ident(nspname)='%s' "\
845 " OR '\"' || nspname || '\"' ='%s') "
847 #define Query_for_list_of_enum_values \
848 "SELECT pg_catalog.quote_literal(enumlabel) "\
849 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t "\
850 " WHERE t.oid = e.enumtypid "\
851 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
852 " AND (pg_catalog.quote_ident(typname)='%s' "\
853 " OR '\"' || typname || '\"'='%s') "\
854 " AND pg_catalog.pg_type_is_visible(t.oid)"
856 #define Query_for_list_of_enum_values_with_schema \
857 "SELECT pg_catalog.quote_literal(enumlabel) "\
858 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
859 " WHERE t.oid = e.enumtypid "\
860 " AND n.oid = t.typnamespace "\
861 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
862 " AND (pg_catalog.quote_ident(typname)='%s' "\
863 " OR '\"' || typname || '\"'='%s') "\
864 " AND (pg_catalog.quote_ident(nspname)='%s' "\
865 " OR '\"' || nspname || '\"' ='%s') "
867 #define Query_for_list_of_template_databases \
868 "SELECT pg_catalog.quote_ident(d.datname) "\
869 " FROM pg_catalog.pg_database d "\
870 " WHERE substring(pg_catalog.quote_ident(d.datname),1,%d)='%s' "\
871 " AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
873 #define Query_for_list_of_databases \
874 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
875 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
877 #define Query_for_list_of_tablespaces \
878 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
879 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
881 #define Query_for_list_of_encodings \
882 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
883 " FROM pg_catalog.pg_conversion "\
884 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
886 #define Query_for_list_of_languages \
887 "SELECT pg_catalog.quote_ident(lanname) "\
888 " FROM pg_catalog.pg_language "\
889 " WHERE lanname != 'internal' "\
890 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
892 #define Query_for_list_of_schemas \
893 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
894 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
896 #define Query_for_list_of_alter_system_set_vars \
898 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
899 " WHERE context != 'internal' "\
900 " UNION ALL SELECT 'all') ss "\
901 " WHERE substring(name,1,%d)='%s'"
903 #define Query_for_list_of_set_vars \
905 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
906 " WHERE context IN ('user', 'superuser') "\
907 " UNION ALL SELECT 'constraints' "\
908 " UNION ALL SELECT 'transaction' "\
909 " UNION ALL SELECT 'session' "\
910 " UNION ALL SELECT 'role' "\
911 " UNION ALL SELECT 'tablespace' "\
912 " UNION ALL SELECT 'all') ss "\
913 " WHERE substring(name,1,%d)='%s'"
915 #define Query_for_list_of_show_vars \
917 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
918 " UNION ALL SELECT 'session authorization' "\
919 " UNION ALL SELECT 'all') ss "\
920 " WHERE substring(name,1,%d)='%s'"
922 #define Query_for_list_of_roles \
923 " SELECT pg_catalog.quote_ident(rolname) "\
924 " FROM pg_catalog.pg_roles "\
925 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
927 #define Query_for_list_of_grant_roles \
928 " SELECT pg_catalog.quote_ident(rolname) "\
929 " FROM pg_catalog.pg_roles "\
930 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
931 " UNION ALL SELECT 'PUBLIC'"\
932 " UNION ALL SELECT 'CURRENT_USER'"\
933 " UNION ALL SELECT 'SESSION_USER'"
935 /* the silly-looking length condition is just to eat up the current word */
936 #define Query_for_table_owning_index \
937 "SELECT pg_catalog.quote_ident(c1.relname) "\
938 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
939 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
940 " and (%d = pg_catalog.length('%s'))"\
941 " and pg_catalog.quote_ident(c2.relname)='%s'"\
942 " and pg_catalog.pg_table_is_visible(c2.oid)"
944 /* the silly-looking length condition is just to eat up the current word */
945 #define Query_for_index_of_table \
946 "SELECT pg_catalog.quote_ident(c2.relname) "\
947 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
948 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
949 " and (%d = pg_catalog.length('%s'))"\
950 " and pg_catalog.quote_ident(c1.relname)='%s'"\
951 " and pg_catalog.pg_table_is_visible(c2.oid)"
953 /* the silly-looking length condition is just to eat up the current word */
954 #define Query_for_constraint_of_table \
955 "SELECT pg_catalog.quote_ident(conname) "\
956 " FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
957 " WHERE c1.oid=conrelid and (%d = pg_catalog.length('%s'))"\
958 " and pg_catalog.quote_ident(c1.relname)='%s'"\
959 " and pg_catalog.pg_table_is_visible(c1.oid)"
961 #define Query_for_all_table_constraints \
962 "SELECT pg_catalog.quote_ident(conname) "\
963 " FROM pg_catalog.pg_constraint c "\
964 " WHERE c.conrelid <> 0 "
966 /* the silly-looking length condition is just to eat up the current word */
967 #define Query_for_constraint_of_type \
968 "SELECT pg_catalog.quote_ident(conname) "\
969 " FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
970 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
971 " and pg_catalog.quote_ident(t.typname)='%s'"\
972 " and pg_catalog.pg_type_is_visible(t.oid)"
974 /* the silly-looking length condition is just to eat up the current word */
975 #define Query_for_list_of_tables_for_constraint \
976 "SELECT pg_catalog.quote_ident(relname) "\
977 " FROM pg_catalog.pg_class"\
978 " WHERE (%d = pg_catalog.length('%s'))"\
980 " (SELECT conrelid FROM pg_catalog.pg_constraint "\
981 " WHERE pg_catalog.quote_ident(conname)='%s')"
983 /* the silly-looking length condition is just to eat up the current word */
984 #define Query_for_rule_of_table \
985 "SELECT pg_catalog.quote_ident(rulename) "\
986 " FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
987 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
988 " and pg_catalog.quote_ident(c1.relname)='%s'"\
989 " and pg_catalog.pg_table_is_visible(c1.oid)"
991 /* the silly-looking length condition is just to eat up the current word */
992 #define Query_for_list_of_tables_for_rule \
993 "SELECT pg_catalog.quote_ident(relname) "\
994 " FROM pg_catalog.pg_class"\
995 " WHERE (%d = pg_catalog.length('%s'))"\
997 " (SELECT ev_class FROM pg_catalog.pg_rewrite "\
998 " WHERE pg_catalog.quote_ident(rulename)='%s')"
1000 /* the silly-looking length condition is just to eat up the current word */
1001 #define Query_for_trigger_of_table \
1002 "SELECT pg_catalog.quote_ident(tgname) "\
1003 " FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
1004 " WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
1005 " and pg_catalog.quote_ident(c1.relname)='%s'"\
1006 " and pg_catalog.pg_table_is_visible(c1.oid)"\
1007 " and not tgisinternal"
1009 /* the silly-looking length condition is just to eat up the current word */
1010 #define Query_for_list_of_tables_for_trigger \
1011 "SELECT pg_catalog.quote_ident(relname) "\
1012 " FROM pg_catalog.pg_class"\
1013 " WHERE (%d = pg_catalog.length('%s'))"\
1015 " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
1016 " WHERE pg_catalog.quote_ident(tgname)='%s')"
1018 #define Query_for_list_of_ts_configurations \
1019 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
1020 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
1022 #define Query_for_list_of_ts_dictionaries \
1023 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
1024 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
1026 #define Query_for_list_of_ts_parsers \
1027 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
1028 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
1030 #define Query_for_list_of_ts_templates \
1031 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
1032 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
1034 #define Query_for_list_of_fdws \
1035 " SELECT pg_catalog.quote_ident(fdwname) "\
1036 " FROM pg_catalog.pg_foreign_data_wrapper "\
1037 " WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
1039 #define Query_for_list_of_servers \
1040 " SELECT pg_catalog.quote_ident(srvname) "\
1041 " FROM pg_catalog.pg_foreign_server "\
1042 " WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
1044 #define Query_for_list_of_user_mappings \
1045 " SELECT pg_catalog.quote_ident(usename) "\
1046 " FROM pg_catalog.pg_user_mappings "\
1047 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
1049 #define Query_for_list_of_access_methods \
1050 " SELECT pg_catalog.quote_ident(amname) "\
1051 " FROM pg_catalog.pg_am "\
1052 " WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
1054 /* the silly-looking length condition is just to eat up the current word */
1055 #define Query_for_list_of_arguments \
1056 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
1057 " FROM pg_catalog.pg_proc "\
1058 " WHERE (%d = pg_catalog.length('%s'))"\
1059 " AND (pg_catalog.quote_ident(proname)='%s'"\
1060 " OR '\"' || proname || '\"'='%s') "\
1061 " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
1063 /* the silly-looking length condition is just to eat up the current word */
1064 #define Query_for_list_of_arguments_with_schema \
1065 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
1066 " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
1067 " WHERE (%d = pg_catalog.length('%s'))"\
1068 " AND n.oid = p.pronamespace "\
1069 " AND (pg_catalog.quote_ident(proname)='%s' "\
1070 " OR '\"' || proname || '\"' ='%s') "\
1071 " AND (pg_catalog.quote_ident(nspname)='%s' "\
1072 " OR '\"' || nspname || '\"' ='%s') "
1074 #define Query_for_list_of_extensions \
1075 " SELECT pg_catalog.quote_ident(extname) "\
1076 " FROM pg_catalog.pg_extension "\
1077 " WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
1079 #define Query_for_list_of_available_extensions \
1080 " SELECT pg_catalog.quote_ident(name) "\
1081 " FROM pg_catalog.pg_available_extensions "\
1082 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
1084 /* the silly-looking length condition is just to eat up the current word */
1085 #define Query_for_list_of_available_extension_versions \
1086 " SELECT pg_catalog.quote_ident(version) "\
1087 " FROM pg_catalog.pg_available_extension_versions "\
1088 " WHERE (%d = pg_catalog.length('%s'))"\
1089 " AND pg_catalog.quote_ident(name)='%s'"
1091 /* the silly-looking length condition is just to eat up the current word */
1092 #define Query_for_list_of_available_extension_versions_with_TO \
1093 " SELECT 'TO ' || pg_catalog.quote_ident(version) "\
1094 " FROM pg_catalog.pg_available_extension_versions "\
1095 " WHERE (%d = pg_catalog.length('%s'))"\
1096 " AND pg_catalog.quote_ident(name)='%s'"
1098 #define Query_for_list_of_prepared_statements \
1099 " SELECT pg_catalog.quote_ident(name) "\
1100 " FROM pg_catalog.pg_prepared_statements "\
1101 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
1103 #define Query_for_list_of_event_triggers \
1104 " SELECT pg_catalog.quote_ident(evtname) "\
1105 " FROM pg_catalog.pg_event_trigger "\
1106 " WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
1108 #define Query_for_list_of_tablesample_methods \
1109 " SELECT pg_catalog.quote_ident(proname) "\
1110 " FROM pg_catalog.pg_proc "\
1111 " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
1112 " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
1113 " substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
1115 #define Query_for_list_of_policies \
1116 " SELECT pg_catalog.quote_ident(polname) "\
1117 " FROM pg_catalog.pg_policy "\
1118 " WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
1120 #define Query_for_list_of_tables_for_policy \
1121 "SELECT pg_catalog.quote_ident(relname) "\
1122 " FROM pg_catalog.pg_class"\
1123 " WHERE (%d = pg_catalog.length('%s'))"\
1125 " (SELECT polrelid FROM pg_catalog.pg_policy "\
1126 " WHERE pg_catalog.quote_ident(polname)='%s')"
1128 #define Query_for_enum \
1129 " SELECT name FROM ( "\
1130 " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
1131 " FROM pg_catalog.pg_settings "\
1132 " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
1134 " SELECT 'DEFAULT' ) ss "\
1135 " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
1137 /* the silly-looking length condition is just to eat up the current word */
1138 #define Query_for_partition_of_table \
1139 "SELECT pg_catalog.quote_ident(c2.relname) "\
1140 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i"\
1141 " WHERE c1.oid=i.inhparent and i.inhrelid=c2.oid"\
1142 " and (%d = pg_catalog.length('%s'))"\
1143 " and pg_catalog.quote_ident(c1.relname)='%s'"\
1144 " and pg_catalog.pg_table_is_visible(c2.oid)"\
1145 " and c2.relispartition = 'true'"
1148 * These object types were introduced later than our support cutoff of
1149 * server version 7.4. We use the VersionedQuery infrastructure so that
1150 * we don't send certain-to-fail queries to older servers.
1153 static const VersionedQuery Query_for_list_of_publications[] = {
1155 " SELECT pg_catalog.quote_ident(pubname) "
1156 " FROM pg_catalog.pg_publication "
1157 " WHERE substring(pg_catalog.quote_ident(pubname),1,%d)='%s'"
1162 static const VersionedQuery Query_for_list_of_subscriptions[] = {
1164 " SELECT pg_catalog.quote_ident(s.subname) "
1165 " FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "
1166 " WHERE substring(pg_catalog.quote_ident(s.subname),1,%d)='%s' "
1167 " AND d.datname = pg_catalog.current_database() "
1168 " AND s.subdbid = d.oid"
1174 * This is a list of all "things" in Pgsql, which can show up after CREATE or
1175 * DROP; and there is also a query to get a list of them.
1181 const char *query; /* simple query, or NULL */
1182 const VersionedQuery *vquery; /* versioned query, or NULL */
1183 const SchemaQuery *squery; /* schema query, or NULL */
1184 const bits32 flags; /* visibility flags, see below */
1187 #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
1188 #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
1189 #define THING_NO_ALTER (1 << 2) /* should not show up after ALTER */
1190 #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
1192 static const pgsql_thing_t words_after_create[] = {
1193 {"ACCESS METHOD", NULL, NULL, NULL, THING_NO_ALTER},
1194 {"AGGREGATE", NULL, NULL, Query_for_list_of_aggregates},
1195 {"CAST", NULL, NULL, NULL}, /* Casts have complex structures for names, so
1197 {"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'"},
1200 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
1201 * to be used only by pg_dump.
1203 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, NULL, THING_NO_SHOW},
1204 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
1205 {"DATABASE", Query_for_list_of_databases},
1206 {"DEFAULT PRIVILEGES", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1207 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, NULL, THING_NO_SHOW},
1208 {"DOMAIN", NULL, NULL, &Query_for_list_of_domains},
1209 {"EVENT TRIGGER", NULL, NULL, NULL},
1210 {"EXTENSION", Query_for_list_of_extensions},
1211 {"FOREIGN DATA WRAPPER", NULL, NULL, NULL},
1212 {"FOREIGN TABLE", NULL, NULL, NULL},
1213 {"FUNCTION", NULL, NULL, Query_for_list_of_functions},
1214 {"GROUP", Query_for_list_of_roles},
1215 {"INDEX", NULL, NULL, &Query_for_list_of_indexes},
1216 {"LANGUAGE", Query_for_list_of_languages},
1217 {"LARGE OBJECT", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1218 {"MATERIALIZED VIEW", NULL, NULL, &Query_for_list_of_matviews},
1219 {"OPERATOR", NULL, NULL, NULL}, /* Querying for this is probably not such
1221 {"OWNED", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_ALTER}, /* for DROP OWNED BY ... */
1222 {"PARSER", Query_for_list_of_ts_parsers, NULL, NULL, THING_NO_SHOW},
1223 {"POLICY", NULL, NULL, NULL},
1224 {"PROCEDURE", NULL, NULL, Query_for_list_of_procedures},
1225 {"PUBLICATION", NULL, Query_for_list_of_publications},
1226 {"ROLE", Query_for_list_of_roles},
1227 {"ROUTINE", NULL, NULL, &Query_for_list_of_routines, THING_NO_CREATE},
1228 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
1229 {"SCHEMA", Query_for_list_of_schemas},
1230 {"SEQUENCE", NULL, NULL, &Query_for_list_of_sequences},
1231 {"SERVER", Query_for_list_of_servers},
1232 {"STATISTICS", NULL, NULL, &Query_for_list_of_statistics},
1233 {"SUBSCRIPTION", NULL, Query_for_list_of_subscriptions},
1234 {"SYSTEM", NULL, NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1235 {"TABLE", NULL, NULL, &Query_for_list_of_tables},
1236 {"TABLESPACE", Query_for_list_of_tablespaces},
1237 {"TEMP", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE
1239 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, NULL, THING_NO_SHOW},
1240 {"TEMPORARY", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMPORARY
1242 {"TEXT SEARCH", NULL, NULL, NULL},
1243 {"TRANSFORM", NULL, NULL, NULL},
1244 {"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"},
1245 {"TYPE", NULL, NULL, &Query_for_list_of_datatypes},
1246 {"UNIQUE", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNIQUE
1248 {"UNLOGGED", NULL, NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNLOGGED
1250 {"USER", Query_for_list_of_roles " UNION SELECT 'MAPPING FOR'"},
1251 {"USER MAPPING FOR", NULL, NULL, NULL},
1252 {"VIEW", NULL, NULL, &Query_for_list_of_views},
1253 {NULL} /* end of list */
1257 /* Forward declaration of functions */
1258 static char **psql_completion(const char *text, int start, int end);
1259 static char *create_command_generator(const char *text, int state);
1260 static char *drop_command_generator(const char *text, int state);
1261 static char *alter_command_generator(const char *text, int state);
1262 static char *complete_from_query(const char *text, int state);
1263 static char *complete_from_versioned_query(const char *text, int state);
1264 static char *complete_from_schema_query(const char *text, int state);
1265 static char *complete_from_versioned_schema_query(const char *text, int state);
1266 static char *_complete_from_query(const char *simple_query,
1267 const SchemaQuery *schema_query,
1268 const char *text, int state);
1269 static char *complete_from_list(const char *text, int state);
1270 static char *complete_from_const(const char *text, int state);
1271 static void append_variable_names(char ***varnames, int *nvars,
1272 int *maxvars, const char *varname,
1273 const char *prefix, const char *suffix);
1274 static char **complete_from_variables(const char *text,
1275 const char *prefix, const char *suffix, bool need_value);
1276 static char *complete_from_files(const char *text, int state);
1278 static char *pg_strdup_keyword_case(const char *s, const char *ref);
1279 static char *escape_string(const char *text);
1280 static PGresult *exec_query(const char *query);
1282 static char **get_previous_words(int point, char **buffer, int *nwords);
1284 static char *get_guctype(const char *varname);
1287 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
1288 static char *dequote_file_name(char *text, char quote_char);
1293 * Initialize the readline library for our purposes.
1296 initialize_readline(void)
1298 rl_readline_name = (char *) pset.progname;
1299 rl_attempted_completion_function = psql_completion;
1301 rl_basic_word_break_characters = WORD_BREAKS;
1303 completion_max_records = 1000;
1306 * There is a variable rl_completion_query_items for this but apparently
1307 * it's not defined everywhere.
1312 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1313 * using case-insensitive or case-sensitive comparisons.
1315 * If pattern is NULL, it's a wild card that matches any word.
1316 * If pattern begins with '!', the result is negated, ie we check that 'word'
1317 * does *not* match any alternative appearing in the rest of 'pattern'.
1318 * Any alternative can end with '*' which is a wild card, i.e., it means
1319 * match any word that matches the characters so far. (We do not currently
1320 * support '*' elsewhere than the end of an alternative.)
1322 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1323 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1324 * just be written directly in patterns.)
1326 #define MatchAny NULL
1327 #define MatchAnyExcept(pattern) ("!" pattern)
1330 word_matches_internal(const char *pattern,
1332 bool case_sensitive)
1337 /* NULL pattern matches anything. */
1338 if (pattern == NULL)
1341 /* Handle negated patterns from the MatchAnyExcept macro. */
1342 if (*pattern == '!')
1343 return !word_matches_internal(pattern + 1, word, case_sensitive);
1345 /* Else consider each alternative in the pattern. */
1346 wordlen = strlen(word);
1351 /* Find end of current alternative. */
1353 while (*c != '\0' && *c != '|')
1355 /* Was there a wild card? (Assumes first alternative is not empty) */
1358 /* Yes, wildcard match? */
1359 patternlen = c - pattern - 1;
1360 if (wordlen >= patternlen &&
1362 strncmp(word, pattern, patternlen) == 0 :
1363 pg_strncasecmp(word, pattern, patternlen) == 0))
1368 /* No, plain match? */
1369 patternlen = c - pattern;
1370 if (wordlen == patternlen &&
1372 strncmp(word, pattern, wordlen) == 0 :
1373 pg_strncasecmp(word, pattern, wordlen) == 0))
1376 /* Out of alternatives? */
1379 /* Nope, try next alternative. */
1387 * There are enough matching calls below that it seems worth having these two
1388 * interface routines rather than including a third parameter in every call.
1390 * word_matches --- match case-insensitively.
1393 word_matches(const char *pattern, const char *word)
1395 return word_matches_internal(pattern, word, false);
1399 * word_matches_cs --- match case-sensitively.
1402 word_matches_cs(const char *pattern, const char *word)
1404 return word_matches_internal(pattern, word, true);
1408 * Check if the final character of 's' is 'c'.
1411 ends_with(const char *s, char c)
1413 size_t length = strlen(s);
1415 return (length > 0 && s[length - 1] == c);
1419 * The completion function.
1421 * According to readline spec this gets passed the text entered so far and its
1422 * start and end positions in the readline buffer. The return value is some
1423 * partially obscure list format that can be generated by readline's
1424 * completion_matches() function, so we don't have to worry about it.
1427 psql_completion(const char *text, int start, int end)
1429 /* This is the variable we'll return. */
1430 char **matches = NULL;
1432 /* Workspace for parsed words. */
1435 /* This array will contain pointers to parsed words. */
1436 char **previous_words;
1438 /* The number of words found on the input line. */
1439 int previous_words_count;
1442 * For compactness, we use these macros to reference previous_words[].
1443 * Caution: do not access a previous_words[] entry without having checked
1444 * previous_words_count to be sure it's valid. In most cases below, that
1445 * check is implicit in a TailMatches() or similar macro, but in some
1446 * places we have to check it explicitly.
1448 #define prev_wd (previous_words[0])
1449 #define prev2_wd (previous_words[1])
1450 #define prev3_wd (previous_words[2])
1451 #define prev4_wd (previous_words[3])
1452 #define prev5_wd (previous_words[4])
1453 #define prev6_wd (previous_words[5])
1454 #define prev7_wd (previous_words[6])
1455 #define prev8_wd (previous_words[7])
1456 #define prev9_wd (previous_words[8])
1458 /* Macros for matching the last N words before point, case-insensitively. */
1459 #define TailMatches1(p1) \
1460 (previous_words_count >= 1 && \
1461 word_matches(p1, prev_wd))
1463 #define TailMatches2(p2, p1) \
1464 (previous_words_count >= 2 && \
1465 word_matches(p1, prev_wd) && \
1466 word_matches(p2, prev2_wd))
1468 #define TailMatches3(p3, p2, p1) \
1469 (previous_words_count >= 3 && \
1470 word_matches(p1, prev_wd) && \
1471 word_matches(p2, prev2_wd) && \
1472 word_matches(p3, prev3_wd))
1474 #define TailMatches4(p4, p3, p2, p1) \
1475 (previous_words_count >= 4 && \
1476 word_matches(p1, prev_wd) && \
1477 word_matches(p2, prev2_wd) && \
1478 word_matches(p3, prev3_wd) && \
1479 word_matches(p4, prev4_wd))
1481 #define TailMatches5(p5, p4, p3, p2, p1) \
1482 (previous_words_count >= 5 && \
1483 word_matches(p1, prev_wd) && \
1484 word_matches(p2, prev2_wd) && \
1485 word_matches(p3, prev3_wd) && \
1486 word_matches(p4, prev4_wd) && \
1487 word_matches(p5, prev5_wd))
1489 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1490 (previous_words_count >= 6 && \
1491 word_matches(p1, prev_wd) && \
1492 word_matches(p2, prev2_wd) && \
1493 word_matches(p3, prev3_wd) && \
1494 word_matches(p4, prev4_wd) && \
1495 word_matches(p5, prev5_wd) && \
1496 word_matches(p6, prev6_wd))
1498 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1499 (previous_words_count >= 7 && \
1500 word_matches(p1, prev_wd) && \
1501 word_matches(p2, prev2_wd) && \
1502 word_matches(p3, prev3_wd) && \
1503 word_matches(p4, prev4_wd) && \
1504 word_matches(p5, prev5_wd) && \
1505 word_matches(p6, prev6_wd) && \
1506 word_matches(p7, prev7_wd))
1508 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1509 (previous_words_count >= 8 && \
1510 word_matches(p1, prev_wd) && \
1511 word_matches(p2, prev2_wd) && \
1512 word_matches(p3, prev3_wd) && \
1513 word_matches(p4, prev4_wd) && \
1514 word_matches(p5, prev5_wd) && \
1515 word_matches(p6, prev6_wd) && \
1516 word_matches(p7, prev7_wd) && \
1517 word_matches(p8, prev8_wd))
1519 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1520 (previous_words_count >= 9 && \
1521 word_matches(p1, prev_wd) && \
1522 word_matches(p2, prev2_wd) && \
1523 word_matches(p3, prev3_wd) && \
1524 word_matches(p4, prev4_wd) && \
1525 word_matches(p5, prev5_wd) && \
1526 word_matches(p6, prev6_wd) && \
1527 word_matches(p7, prev7_wd) && \
1528 word_matches(p8, prev8_wd) && \
1529 word_matches(p9, prev9_wd))
1531 /* Macros for matching the last N words before point, case-sensitively. */
1532 #define TailMatchesCS1(p1) \
1533 (previous_words_count >= 1 && \
1534 word_matches_cs(p1, prev_wd))
1535 #define TailMatchesCS2(p2, p1) \
1536 (previous_words_count >= 2 && \
1537 word_matches_cs(p1, prev_wd) && \
1538 word_matches_cs(p2, prev2_wd))
1539 #define TailMatchesCS3(p3, p2, p1) \
1540 (previous_words_count >= 3 && \
1541 word_matches_cs(p1, prev_wd) && \
1542 word_matches_cs(p2, prev2_wd) && \
1543 word_matches_cs(p3, prev3_wd))
1544 #define TailMatchesCS4(p4, p3, p2, p1) \
1545 (previous_words_count >= 4 && \
1546 word_matches_cs(p1, prev_wd) && \
1547 word_matches_cs(p2, prev2_wd) && \
1548 word_matches_cs(p3, prev3_wd) && \
1549 word_matches_cs(p4, prev4_wd))
1552 * Macros for matching N words beginning at the start of the line,
1553 * case-insensitively.
1555 #define Matches1(p1) \
1556 (previous_words_count == 1 && \
1558 #define Matches2(p1, p2) \
1559 (previous_words_count == 2 && \
1560 TailMatches2(p1, p2))
1561 #define Matches3(p1, p2, p3) \
1562 (previous_words_count == 3 && \
1563 TailMatches3(p1, p2, p3))
1564 #define Matches4(p1, p2, p3, p4) \
1565 (previous_words_count == 4 && \
1566 TailMatches4(p1, p2, p3, p4))
1567 #define Matches5(p1, p2, p3, p4, p5) \
1568 (previous_words_count == 5 && \
1569 TailMatches5(p1, p2, p3, p4, p5))
1570 #define Matches6(p1, p2, p3, p4, p5, p6) \
1571 (previous_words_count == 6 && \
1572 TailMatches6(p1, p2, p3, p4, p5, p6))
1573 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1574 (previous_words_count == 7 && \
1575 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1576 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1577 (previous_words_count == 8 && \
1578 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1579 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1580 (previous_words_count == 9 && \
1581 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1584 * Macros for matching N words at the start of the line, regardless of
1585 * what is after them, case-insensitively.
1587 #define HeadMatches1(p1) \
1588 (previous_words_count >= 1 && \
1589 word_matches(p1, previous_words[previous_words_count - 1]))
1591 #define HeadMatches2(p1, p2) \
1592 (previous_words_count >= 2 && \
1593 word_matches(p1, previous_words[previous_words_count - 1]) && \
1594 word_matches(p2, previous_words[previous_words_count - 2]))
1596 #define HeadMatches3(p1, p2, p3) \
1597 (previous_words_count >= 3 && \
1598 word_matches(p1, previous_words[previous_words_count - 1]) && \
1599 word_matches(p2, previous_words[previous_words_count - 2]) && \
1600 word_matches(p3, previous_words[previous_words_count - 3]))
1602 /* Known command-starting keywords. */
1603 static const char *const sql_commands[] = {
1604 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CALL", "CHECKPOINT", "CLOSE", "CLUSTER",
1605 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1606 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1607 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1608 "MOVE", "NOTIFY", "PREPARE",
1609 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1610 "RESET", "REVOKE", "ROLLBACK",
1611 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1612 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1616 /* psql's backslash commands. */
1617 static const char *const backslash_commands[] = {
1619 "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1620 "\\copyright", "\\crosstabview",
1621 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1622 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1623 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1624 "\\dm", "\\dn", "\\do", "\\dO", "\\dp",
1625 "\\drds", "\\dRs", "\\dRp", "\\ds", "\\dS",
1626 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1627 "\\e", "\\echo", "\\ef", "\\elif", "\\else", "\\encoding",
1628 "\\endif", "\\errverbose", "\\ev",
1630 "\\g", "\\gdesc", "\\gexec", "\\gset", "\\gx",
1631 "\\h", "\\help", "\\H",
1632 "\\i", "\\if", "\\ir",
1633 "\\l", "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1635 "\\p", "\\password", "\\prompt", "\\pset",
1638 "\\s", "\\set", "\\setenv", "\\sf", "\\sv",
1639 "\\t", "\\T", "\\timing",
1648 (void) end; /* "end" is not used */
1650 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1651 rl_completion_append_character = ' ';
1654 /* Clear a few things. */
1655 completion_charp = NULL;
1656 completion_charpp = NULL;
1657 completion_info_charp = NULL;
1658 completion_info_charp2 = NULL;
1661 * Scan the input line to extract the words before our current position.
1662 * According to those we'll make some smart decisions on what the user is
1663 * probably intending to type.
1665 previous_words = get_previous_words(start,
1667 &previous_words_count);
1669 /* If current word is a backslash command, offer completions for that */
1670 if (text[0] == '\\')
1671 COMPLETE_WITH_LIST_CS(backslash_commands);
1673 /* If current word is a variable interpolation, handle that case */
1674 else if (text[0] == ':' && text[1] != ':')
1676 if (text[1] == '\'')
1677 matches = complete_from_variables(text, ":'", "'", true);
1678 else if (text[1] == '"')
1679 matches = complete_from_variables(text, ":\"", "\"", true);
1681 matches = complete_from_variables(text, ":", "", true);
1684 /* If no previous word, suggest one of the basic sql commands */
1685 else if (previous_words_count == 0)
1686 COMPLETE_WITH_LIST(sql_commands);
1689 /* complete with something you can create */
1690 else if (TailMatches1("CREATE"))
1691 matches = completion_matches(text, create_command_generator);
1693 /* DROP, but not DROP embedded in other commands */
1694 /* complete with something you can drop */
1695 else if (Matches1("DROP"))
1696 matches = completion_matches(text, drop_command_generator);
1701 else if (Matches2("ALTER", "TABLE"))
1702 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1703 "UNION SELECT 'ALL IN TABLESPACE'");
1705 /* ALTER something */
1706 else if (Matches1("ALTER"))
1707 matches = completion_matches(text, alter_command_generator);
1708 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1709 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1710 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1711 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1712 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1713 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1714 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1715 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1716 COMPLETE_WITH_CONST("SET TABLESPACE");
1717 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> */
1718 else if (Matches3("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
1719 COMPLETE_WITH_CONST("(");
1720 /* ALTER AGGREGATE,FUNCTION,PROCEDURE,ROUTINE <name> (...) */
1721 else if (Matches4("ALTER", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny))
1723 if (ends_with(prev_wd, ')'))
1724 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1726 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1728 /* ALTER PUBLICATION <name> */
1729 else if (Matches3("ALTER", "PUBLICATION", MatchAny))
1730 COMPLETE_WITH_LIST5("ADD TABLE", "DROP TABLE", "OWNER TO", "RENAME TO", "SET");
1731 /* ALTER PUBLICATION <name> SET */
1732 else if (Matches4("ALTER", "PUBLICATION", MatchAny, "SET"))
1733 COMPLETE_WITH_LIST2("(", "TABLE");
1734 /* ALTER PUBLICATION <name> SET ( */
1735 else if (HeadMatches3("ALTER", "PUBLICATION", MatchAny) && TailMatches2("SET", "("))
1736 COMPLETE_WITH_CONST("publish");
1737 /* ALTER SUBSCRIPTION <name> */
1738 else if (Matches3("ALTER", "SUBSCRIPTION", MatchAny))
1739 COMPLETE_WITH_LIST7("CONNECTION", "ENABLE", "DISABLE", "OWNER TO",
1740 "RENAME TO", "REFRESH PUBLICATION", "SET");
1741 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION */
1742 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1743 TailMatches2("REFRESH", "PUBLICATION"))
1744 COMPLETE_WITH_CONST("WITH (");
1745 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( */
1746 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1747 TailMatches4("REFRESH", "PUBLICATION", "WITH", "("))
1748 COMPLETE_WITH_CONST("copy_data");
1749 /* ALTER SUBSCRIPTION <name> SET */
1750 else if (Matches4("ALTER", "SUBSCRIPTION", MatchAny, "SET"))
1751 COMPLETE_WITH_LIST2("(", "PUBLICATION");
1752 /* ALTER SUBSCRIPTION <name> SET ( */
1753 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "("))
1754 COMPLETE_WITH_LIST2("slot_name", "synchronous_commit");
1755 /* ALTER SUBSCRIPTION <name> SET PUBLICATION */
1756 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "PUBLICATION"))
1758 /* complete with nothing here as this refers to remote publications */
1760 /* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> */
1761 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1762 TailMatches3("SET", "PUBLICATION", MatchAny))
1763 COMPLETE_WITH_CONST("WITH (");
1764 /* ALTER SUBSCRIPTION <name> SET PUBLICATION <name> WITH ( */
1765 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1766 TailMatches5("SET", "PUBLICATION", MatchAny, "WITH", "("))
1767 COMPLETE_WITH_LIST2("copy_data", "refresh");
1768 /* ALTER SCHEMA <name> */
1769 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1770 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1772 /* ALTER COLLATION <name> */
1773 else if (Matches3("ALTER", "COLLATION", MatchAny))
1774 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1776 /* ALTER CONVERSION <name> */
1777 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1778 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1780 /* ALTER DATABASE <name> */
1781 else if (Matches3("ALTER", "DATABASE", MatchAny))
1782 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1783 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1784 "CONNECTION LIMIT");
1786 /* ALTER EVENT TRIGGER */
1787 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1788 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1790 /* ALTER EVENT TRIGGER <name> */
1791 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1792 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1794 /* ALTER EVENT TRIGGER <name> ENABLE */
1795 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1796 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1798 /* ALTER EXTENSION <name> */
1799 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1800 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1802 /* ALTER EXTENSION <name> UPDATE */
1803 else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
1805 completion_info_charp = prev2_wd;
1806 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
1809 /* ALTER EXTENSION <name> UPDATE TO */
1810 else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
1812 completion_info_charp = prev3_wd;
1813 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
1817 else if (Matches2("ALTER", "FOREIGN"))
1818 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1820 /* ALTER FOREIGN DATA WRAPPER <name> */
1821 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1822 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1824 /* ALTER FOREIGN TABLE <name> */
1825 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1827 static const char *const list_ALTER_FOREIGN_TABLE[] =
1828 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1829 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1830 "VALIDATE CONSTRAINT", NULL};
1832 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1836 else if (Matches2("ALTER", "INDEX"))
1837 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1838 "UNION SELECT 'ALL IN TABLESPACE'");
1839 /* ALTER INDEX <name> */
1840 else if (Matches3("ALTER", "INDEX", MatchAny))
1841 COMPLETE_WITH_LIST6("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET",
1842 "RESET", "ATTACH PARTITION");
1843 else if (Matches4("ALTER", "INDEX", MatchAny, "ATTACH"))
1844 COMPLETE_WITH_CONST("PARTITION");
1845 else if (Matches5("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION"))
1846 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
1847 /* ALTER INDEX <name> ALTER COLUMN <colnum> */
1848 else if (Matches6("ALTER", "INDEX", MatchAny, "ALTER", "COLUMN", MatchAny))
1849 COMPLETE_WITH_CONST("SET STATISTICS");
1850 /* ALTER INDEX <name> SET */
1851 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1852 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1853 /* ALTER INDEX <name> RESET */
1854 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1855 COMPLETE_WITH_CONST("(");
1856 /* ALTER INDEX <foo> SET|RESET ( */
1857 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1858 COMPLETE_WITH_LIST7("fillfactor", "recheck_on_update",
1859 "fastupdate", "gin_pending_list_limit", /* GIN */
1860 "buffering", /* GiST */
1861 "pages_per_range", "autosummarize" /* BRIN */
1863 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1864 COMPLETE_WITH_LIST7("fillfactor =", "recheck_on_update =",
1865 "fastupdate =", "gin_pending_list_limit =", /* GIN */
1866 "buffering =", /* GiST */
1867 "pages_per_range =", "autosummarize =" /* BRIN */
1870 /* ALTER LANGUAGE <name> */
1871 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1872 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1874 /* ALTER LARGE OBJECT <oid> */
1875 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1876 COMPLETE_WITH_CONST("OWNER TO");
1878 /* ALTER MATERIALIZED VIEW */
1879 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1880 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1881 "UNION SELECT 'ALL IN TABLESPACE'");
1883 /* ALTER USER,ROLE <name> */
1884 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1885 !TailMatches2("USER", "MAPPING"))
1887 static const char *const list_ALTERUSER[] =
1888 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1889 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1890 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1891 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1892 "REPLICATION", "RESET", "SET", "SUPERUSER",
1893 "VALID UNTIL", "WITH", NULL};
1895 COMPLETE_WITH_LIST(list_ALTERUSER);
1898 /* ALTER USER,ROLE <name> WITH */
1899 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1901 /* Similar to the above, but don't complete "WITH" again. */
1902 static const char *const list_ALTERUSER_WITH[] =
1903 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1904 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1905 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1906 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1907 "REPLICATION", "RESET", "SET", "SUPERUSER",
1908 "VALID UNTIL", NULL};
1910 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1913 /* ALTER DEFAULT PRIVILEGES */
1914 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1915 COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
1916 /* ALTER DEFAULT PRIVILEGES FOR */
1917 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1918 COMPLETE_WITH_CONST("ROLE");
1919 /* ALTER DEFAULT PRIVILEGES IN */
1920 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1921 COMPLETE_WITH_CONST("SCHEMA");
1922 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1923 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1925 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
1926 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1927 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1929 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
1930 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1931 else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1933 COMPLETE_WITH_CONST("ROLE");
1934 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
1935 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1936 else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1937 MatchAny, "IN", "SCHEMA", MatchAny) ||
1938 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1939 MatchAny, "FOR", "ROLE|USER", MatchAny))
1940 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1941 /* ALTER DOMAIN <name> */
1942 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1943 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1944 "VALIDATE CONSTRAINT");
1945 /* ALTER DOMAIN <sth> DROP */
1946 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1947 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1948 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1949 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1951 completion_info_charp = prev3_wd;
1952 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1954 /* ALTER DOMAIN <sth> RENAME */
1955 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1956 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1957 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1958 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1959 COMPLETE_WITH_CONST("TO");
1961 /* ALTER DOMAIN <sth> SET */
1962 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1963 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1964 /* ALTER SEQUENCE <name> */
1965 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1967 static const char *const list_ALTERSEQUENCE[] =
1968 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1969 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1971 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1973 /* ALTER SEQUENCE <name> NO */
1974 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1975 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1976 /* ALTER SERVER <name> */
1977 else if (Matches3("ALTER", "SERVER", MatchAny))
1978 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1979 /* ALTER SERVER <name> VERSION <version> */
1980 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1981 COMPLETE_WITH_CONST("OPTIONS");
1982 /* ALTER SYSTEM SET, RESET, RESET ALL */
1983 else if (Matches2("ALTER", "SYSTEM"))
1984 COMPLETE_WITH_LIST2("SET", "RESET");
1985 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1986 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1987 else if (Matches4("ALTER", "SYSTEM", "SET", MatchAny))
1988 COMPLETE_WITH_CONST("TO");
1989 /* ALTER VIEW <name> */
1990 else if (Matches3("ALTER", "VIEW", MatchAny))
1991 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1993 /* ALTER MATERIALIZED VIEW <name> */
1994 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1995 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1998 /* ALTER POLICY <name> */
1999 else if (Matches2("ALTER", "POLICY"))
2000 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2001 /* ALTER POLICY <name> ON */
2002 else if (Matches3("ALTER", "POLICY", MatchAny))
2003 COMPLETE_WITH_CONST("ON");
2004 /* ALTER POLICY <name> ON <table> */
2005 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
2007 completion_info_charp = prev2_wd;
2008 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2010 /* ALTER POLICY <name> ON <table> - show options */
2011 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
2012 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
2013 /* ALTER POLICY <name> ON <table> TO <role> */
2014 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2015 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2016 /* ALTER POLICY <name> ON <table> USING ( */
2017 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2018 COMPLETE_WITH_CONST("(");
2019 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
2020 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
2021 COMPLETE_WITH_CONST("(");
2023 /* ALTER RULE <name>, add ON */
2024 else if (Matches3("ALTER", "RULE", MatchAny))
2025 COMPLETE_WITH_CONST("ON");
2027 /* If we have ALTER RULE <name> ON, then add the correct tablename */
2028 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
2030 completion_info_charp = prev2_wd;
2031 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2034 /* ALTER RULE <name> ON <name> */
2035 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
2036 COMPLETE_WITH_CONST("RENAME TO");
2038 /* ALTER STATISTICS <name> */
2039 else if (Matches3("ALTER", "STATISTICS", MatchAny))
2040 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
2042 /* ALTER TRIGGER <name>, add ON */
2043 else if (Matches3("ALTER", "TRIGGER", MatchAny))
2044 COMPLETE_WITH_CONST("ON");
2046 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
2048 completion_info_charp = prev2_wd;
2049 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2053 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
2055 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
2056 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2058 /* ALTER TRIGGER <name> ON <name> */
2059 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
2060 COMPLETE_WITH_CONST("RENAME TO");
2063 * If we detect ALTER TABLE <name>, suggest sub commands
2065 else if (Matches3("ALTER", "TABLE", MatchAny))
2067 static const char *const list_ALTER2[] =
2068 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
2069 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
2070 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", "ATTACH PARTITION",
2071 "DETACH PARTITION", NULL};
2073 COMPLETE_WITH_LIST(list_ALTER2);
2075 /* ALTER TABLE xxx ENABLE */
2076 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
2077 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
2079 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
2080 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
2081 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
2083 completion_info_charp = prev3_wd;
2084 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
2086 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
2088 completion_info_charp = prev4_wd;
2089 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
2091 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
2093 completion_info_charp = prev3_wd;
2094 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
2096 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
2098 completion_info_charp = prev4_wd;
2099 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
2101 /* ALTER TABLE xxx INHERIT */
2102 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
2103 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2104 /* ALTER TABLE xxx NO INHERIT */
2105 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
2106 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2107 /* ALTER TABLE xxx DISABLE */
2108 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
2109 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
2110 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
2112 completion_info_charp = prev3_wd;
2113 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
2115 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
2117 completion_info_charp = prev3_wd;
2118 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
2121 /* ALTER TABLE xxx ALTER */
2122 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
2123 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
2125 /* ALTER TABLE xxx RENAME */
2126 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
2127 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
2128 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
2129 COMPLETE_WITH_ATTR(prev3_wd, "");
2131 /* ALTER TABLE xxx RENAME yyy */
2132 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
2133 COMPLETE_WITH_CONST("TO");
2135 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
2136 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
2137 COMPLETE_WITH_CONST("TO");
2139 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
2140 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
2141 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
2142 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
2143 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
2144 COMPLETE_WITH_ATTR(prev3_wd, "");
2147 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
2148 * provide list of constraints
2150 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
2152 completion_info_charp = prev3_wd;
2153 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
2155 /* ALTER TABLE ALTER [COLUMN] <foo> */
2156 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
2157 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
2158 COMPLETE_WITH_LIST6("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
2159 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
2160 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
2161 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
2162 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
2163 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
2164 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
2165 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
2166 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
2167 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
2168 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
2169 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
2170 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
2171 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
2172 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
2173 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
2174 COMPLETE_WITH_LIST3("DEFAULT", "IDENTITY", "NOT NULL");
2175 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
2176 COMPLETE_WITH_CONST("ON");
2177 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
2179 completion_info_charp = prev3_wd;
2180 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2182 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
2183 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
2184 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
2188 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
2191 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
2192 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2193 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
2194 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
2195 COMPLETE_WITH_CONST("OIDS");
2196 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
2197 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
2198 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
2199 /* ALTER TABLE <foo> RESET */
2200 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
2201 COMPLETE_WITH_CONST("(");
2202 /* ALTER TABLE <foo> SET|RESET ( */
2203 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
2205 static const char *const list_TABLEOPTIONS[] =
2207 "autovacuum_analyze_scale_factor",
2208 "autovacuum_analyze_threshold",
2209 "autovacuum_enabled",
2210 "autovacuum_freeze_max_age",
2211 "autovacuum_freeze_min_age",
2212 "autovacuum_freeze_table_age",
2213 "autovacuum_multixact_freeze_max_age",
2214 "autovacuum_multixact_freeze_min_age",
2215 "autovacuum_multixact_freeze_table_age",
2216 "autovacuum_vacuum_cost_delay",
2217 "autovacuum_vacuum_cost_limit",
2218 "autovacuum_vacuum_scale_factor",
2219 "autovacuum_vacuum_threshold",
2222 "log_autovacuum_min_duration",
2223 "toast.autovacuum_enabled",
2224 "toast.autovacuum_freeze_max_age",
2225 "toast.autovacuum_freeze_min_age",
2226 "toast.autovacuum_freeze_table_age",
2227 "toast.autovacuum_multixact_freeze_max_age",
2228 "toast.autovacuum_multixact_freeze_min_age",
2229 "toast.autovacuum_multixact_freeze_table_age",
2230 "toast.autovacuum_vacuum_cost_delay",
2231 "toast.autovacuum_vacuum_cost_limit",
2232 "toast.autovacuum_vacuum_scale_factor",
2233 "toast.autovacuum_vacuum_threshold",
2234 "toast.log_autovacuum_min_duration",
2235 "user_catalog_table",
2239 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
2241 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
2243 completion_info_charp = prev5_wd;
2244 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2246 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
2247 COMPLETE_WITH_CONST("INDEX");
2248 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
2249 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
2250 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
2251 COMPLETE_WITH_CONST("IDENTITY");
2254 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
2257 else if (Matches5("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
2258 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2259 /* Limited completion support for partition bound specification */
2260 else if (TailMatches3("ATTACH", "PARTITION", MatchAny))
2261 COMPLETE_WITH_LIST2("FOR VALUES", "DEFAULT");
2262 else if (TailMatches2("FOR", "VALUES"))
2263 COMPLETE_WITH_LIST3("FROM (", "IN (", "WITH (");
2266 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
2267 * partitions of <foo>.
2269 else if (Matches5("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
2271 completion_info_charp = prev3_wd;
2272 COMPLETE_WITH_QUERY(Query_for_partition_of_table);
2275 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
2276 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
2277 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
2278 /* ALTER TABLESPACE <foo> SET|RESET */
2279 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
2280 COMPLETE_WITH_CONST("(");
2281 /* ALTER TABLESPACE <foo> SET|RESET ( */
2282 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
2283 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
2284 "effective_io_concurrency");
2286 /* ALTER TEXT SEARCH */
2287 else if (Matches3("ALTER", "TEXT", "SEARCH"))
2288 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2289 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
2290 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
2291 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
2292 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
2293 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2294 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
2296 "OWNER TO", "RENAME TO", "SET SCHEMA");
2298 /* complete ALTER TYPE <foo> with actions */
2299 else if (Matches3("ALTER", "TYPE", MatchAny))
2300 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
2302 "OWNER TO", "RENAME", "SET SCHEMA");
2303 /* complete ALTER TYPE <foo> ADD with actions */
2304 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
2305 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
2306 /* ALTER TYPE <foo> RENAME */
2307 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
2308 COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
2309 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
2310 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
2311 COMPLETE_WITH_CONST("TO");
2314 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
2317 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
2318 COMPLETE_WITH_ATTR(prev3_wd, "");
2319 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
2320 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
2321 COMPLETE_WITH_CONST("TYPE");
2322 /* complete ALTER GROUP <foo> */
2323 else if (Matches3("ALTER", "GROUP", MatchAny))
2324 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
2325 /* complete ALTER GROUP <foo> ADD|DROP with USER */
2326 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
2327 COMPLETE_WITH_CONST("USER");
2328 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
2329 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
2330 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2333 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
2335 else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
2336 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
2339 else if (Matches1("BEGIN"))
2340 COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2342 else if (Matches1("END|ABORT"))
2343 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
2345 else if (Matches1("COMMIT"))
2346 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
2347 /* RELEASE SAVEPOINT */
2348 else if (Matches1("RELEASE"))
2349 COMPLETE_WITH_CONST("SAVEPOINT");
2351 else if (Matches1("ROLLBACK"))
2352 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
2354 else if (Matches1("CALL"))
2355 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures, NULL);
2356 else if (Matches2("CALL", MatchAny))
2357 COMPLETE_WITH_CONST("(");
2359 else if (Matches1("CLUSTER"))
2360 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
2361 else if (Matches2("CLUSTER", "VERBOSE"))
2362 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2363 /* If we have CLUSTER <sth>, then add "USING" */
2364 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
2365 COMPLETE_WITH_CONST("USING");
2366 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
2367 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
2368 COMPLETE_WITH_CONST("USING");
2369 /* If we have CLUSTER <sth> USING, then add the index as well */
2370 else if (Matches3("CLUSTER", MatchAny, "USING") ||
2371 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
2373 completion_info_charp = prev2_wd;
2374 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2378 else if (Matches1("COMMENT"))
2379 COMPLETE_WITH_CONST("ON");
2380 else if (Matches2("COMMENT", "ON"))
2382 static const char *const list_COMMENT[] =
2383 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
2384 "EVENT TRIGGER", "EXTENSION",
2385 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2386 "SERVER", "INDEX", "LANGUAGE", "POLICY", "PUBLICATION", "RULE",
2387 "SCHEMA", "SEQUENCE", "STATISTICS", "SUBSCRIPTION",
2388 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
2389 "PROCEDURE", "ROUTINE",
2390 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
2391 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
2393 COMPLETE_WITH_LIST(list_COMMENT);
2395 else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
2396 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2397 else if (Matches3("COMMENT", "ON", "FOREIGN"))
2398 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2399 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
2400 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2401 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
2402 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
2403 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
2404 COMPLETE_WITH_CONST("ON");
2405 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2407 completion_info_charp = prev2_wd;
2408 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
2410 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
2411 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2412 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
2413 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2414 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
2415 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2416 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
2417 COMPLETE_WITH_CONST("IS");
2422 * If we have COPY, offer list of tables or "(" (Also cover the analogous
2423 * backslash command).
2425 else if (Matches1("COPY|\\copy"))
2426 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2427 " UNION ALL SELECT '('");
2428 /* If we have COPY BINARY, complete with list of tables */
2429 else if (Matches2("COPY", "BINARY"))
2430 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2431 /* If we have COPY (, complete it with legal commands */
2432 else if (Matches2("COPY|\\copy", "("))
2433 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
2434 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
2435 else if (Matches2("COPY|\\copy", MatchAny) ||
2436 Matches3("COPY", "BINARY", MatchAny))
2437 COMPLETE_WITH_LIST2("FROM", "TO");
2438 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
2439 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
2440 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
2442 completion_charp = "";
2443 matches = completion_matches(text, complete_from_files);
2446 /* Handle COPY [BINARY] <sth> FROM|TO filename */
2447 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
2448 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
2449 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
2452 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
2453 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
2454 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
2455 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
2458 /* CREATE ACCESS METHOD */
2459 /* Complete "CREATE ACCESS METHOD <name>" */
2460 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
2461 COMPLETE_WITH_CONST("TYPE");
2462 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
2463 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
2464 COMPLETE_WITH_CONST("INDEX");
2465 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
2466 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
2467 COMPLETE_WITH_CONST("HANDLER");
2469 /* CREATE DATABASE */
2470 else if (Matches3("CREATE", "DATABASE", MatchAny))
2471 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2473 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2474 "LC_COLLATE", "LC_CTYPE");
2476 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2477 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2479 /* CREATE EXTENSION */
2480 /* Complete with available extensions rather than installed ones. */
2481 else if (Matches2("CREATE", "EXTENSION"))
2482 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2483 /* CREATE EXTENSION <name> */
2484 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2485 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2486 /* CREATE EXTENSION <name> VERSION */
2487 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2489 completion_info_charp = prev2_wd;
2490 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2493 /* CREATE FOREIGN */
2494 else if (Matches2("CREATE", "FOREIGN"))
2495 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2497 /* CREATE FOREIGN DATA WRAPPER */
2498 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2499 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2501 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2502 /* First off we complete CREATE UNIQUE with "INDEX" */
2503 else if (TailMatches2("CREATE", "UNIQUE"))
2504 COMPLETE_WITH_CONST("INDEX");
2507 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2510 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2511 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2512 " UNION SELECT 'ON'"
2513 " UNION SELECT 'CONCURRENTLY'");
2515 * Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of relations
2516 * that can indexes can be created on
2518 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2519 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2520 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tpm, NULL);
2523 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2526 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2527 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2528 " UNION SELECT 'ON'");
2529 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2530 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2531 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2532 COMPLETE_WITH_CONST("ON");
2535 * Complete INDEX <name> ON <table> with a list of table columns (which
2536 * should really be in parens)
2538 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2539 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2540 COMPLETE_WITH_LIST2("(", "USING");
2541 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2542 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2543 COMPLETE_WITH_ATTR(prev2_wd, "");
2544 /* same if you put in USING */
2545 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2546 COMPLETE_WITH_ATTR(prev4_wd, "");
2547 /* Complete USING with an index method */
2548 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2549 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2550 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2551 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2552 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2553 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2554 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2555 COMPLETE_WITH_CONST("(");
2558 /* Complete "CREATE POLICY <name> ON" */
2559 else if (Matches3("CREATE", "POLICY", MatchAny))
2560 COMPLETE_WITH_CONST("ON");
2561 /* Complete "CREATE POLICY <name> ON <table>" */
2562 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2563 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2564 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
2565 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2566 COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
2567 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
2568 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
2569 COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
2572 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2573 * FOR|TO|USING|WITH CHECK
2575 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
2576 COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
2577 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2578 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2579 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2580 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2581 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2582 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2583 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2584 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2585 COMPLETE_WITH_LIST2("TO", "USING (");
2586 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2587 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2588 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2589 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2590 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2591 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2592 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2593 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2594 COMPLETE_WITH_CONST("(");
2597 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2598 * ALL|SELECT|INSERT|UPDATE|DELETE
2600 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
2601 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2604 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2605 * INSERT TO|WITH CHECK"
2607 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
2608 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2611 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2612 * SELECT|DELETE TO|USING"
2614 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
2615 COMPLETE_WITH_LIST2("TO", "USING (");
2618 * CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR
2619 * ALL|UPDATE TO|USING|WITH CHECK
2621 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
2622 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2625 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO
2628 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
2629 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2632 * Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE
2635 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
2636 COMPLETE_WITH_CONST("(");
2639 /* CREATE PUBLICATION */
2640 else if (Matches3("CREATE", "PUBLICATION", MatchAny))
2641 COMPLETE_WITH_LIST3("FOR TABLE", "FOR ALL TABLES", "WITH (");
2642 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR"))
2643 COMPLETE_WITH_LIST2("TABLE", "ALL TABLES");
2644 /* Complete "CREATE PUBLICATION <name> FOR TABLE <table>" */
2645 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
2646 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2647 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
2648 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
2649 COMPLETE_WITH_CONST("publish");
2652 /* Complete "CREATE RULE <sth>" with "AS ON" */
2653 else if (Matches3("CREATE", "RULE", MatchAny))
2654 COMPLETE_WITH_CONST("AS ON");
2655 /* Complete "CREATE RULE <sth> AS" with "ON" */
2656 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2657 COMPLETE_WITH_CONST("ON");
2658 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2659 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2660 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2661 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2662 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2663 COMPLETE_WITH_CONST("TO");
2664 /* Complete "AS ON <sth> TO" with a table name */
2665 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2666 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2668 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2669 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2670 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2671 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2672 "CYCLE", "OWNED BY", "START WITH");
2673 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2674 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2675 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2677 /* CREATE SERVER <name> */
2678 else if (Matches3("CREATE", "SERVER", MatchAny))
2679 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2681 /* CREATE STATISTICS <name> */
2682 else if (Matches3("CREATE", "STATISTICS", MatchAny))
2683 COMPLETE_WITH_LIST2("(", "ON");
2684 else if (Matches4("CREATE", "STATISTICS", MatchAny, "("))
2685 COMPLETE_WITH_LIST2("ndistinct", "dependencies");
2686 else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
2687 previous_words[0][0] == '(' &&
2688 previous_words[0][strlen(previous_words[0]) - 1] == ')')
2689 COMPLETE_WITH_CONST("ON");
2690 else if (HeadMatches3("CREATE", "STATISTICS", MatchAny) &&
2691 TailMatches1("FROM"))
2692 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2694 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2695 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2696 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2697 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2698 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2699 else if (TailMatches2("CREATE", "UNLOGGED"))
2700 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2701 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
2702 else if (TailMatches2("PARTITION", "BY"))
2703 COMPLETE_WITH_LIST2("RANGE (", "LIST (");
2704 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
2705 else if (TailMatches2("PARTITION", "OF"))
2706 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables, "");
2707 /* Limited completion support for partition bound specification */
2708 else if (TailMatches3("PARTITION", "OF", MatchAny))
2709 COMPLETE_WITH_LIST2("FOR VALUES", "DEFAULT");
2711 /* CREATE TABLESPACE */
2712 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2713 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2714 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2715 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2716 COMPLETE_WITH_CONST("LOCATION");
2718 /* CREATE TEXT SEARCH */
2719 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2720 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2721 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2722 COMPLETE_WITH_CONST("(");
2724 /* CREATE SUBSCRIPTION */
2725 else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
2726 COMPLETE_WITH_CONST("CONNECTION");
2727 else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
2728 COMPLETE_WITH_CONST("PUBLICATION");
2729 else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
2730 MatchAny, "PUBLICATION"))
2732 /* complete with nothing here as this refers to remote publications */
2734 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("PUBLICATION", MatchAny))
2735 COMPLETE_WITH_CONST("WITH (");
2736 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
2737 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
2738 COMPLETE_WITH_LIST6("copy_data", "connect", "create_slot", "enabled",
2739 "slot_name", "synchronous_commit");
2741 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2742 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2743 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2744 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2745 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2746 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2747 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2748 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2749 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2750 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2751 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2752 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2753 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2754 COMPLETE_WITH_LIST2("ON", "OR");
2757 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2760 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2761 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2762 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2763 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2764 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2765 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
2766 COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
2767 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2768 else if (HeadMatches2("CREATE", "TRIGGER") &&
2769 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
2770 COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2771 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
2772 COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
2773 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
2774 COMPLETE_WITH_CONST("AS");
2775 else if (HeadMatches2("CREATE", "TRIGGER") &&
2776 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
2777 TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
2778 COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2779 else if (HeadMatches2("CREATE", "TRIGGER") &&
2780 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
2781 TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
2782 COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2783 else if (HeadMatches2("CREATE", "TRIGGER") &&
2784 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2785 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2786 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
2787 TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
2788 COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
2789 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
2790 COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
2791 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
2792 COMPLETE_WITH_LIST2("ROW", "STATEMENT");
2793 else if (HeadMatches2("CREATE", "TRIGGER") &&
2794 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
2795 TailMatches2("FOR", "ROW|STATEMENT")))
2796 COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
2797 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2798 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2799 COMPLETE_WITH_CONST("PROCEDURE");
2800 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
2801 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2803 /* CREATE ROLE,USER,GROUP <name> */
2804 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2805 !TailMatches2("USER", "MAPPING"))
2807 static const char *const list_CREATEROLE[] =
2808 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2809 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2810 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2811 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2812 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2813 "VALID UNTIL", "WITH", NULL};
2815 COMPLETE_WITH_LIST(list_CREATEROLE);
2818 /* CREATE ROLE,USER,GROUP <name> WITH */
2819 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2821 /* Similar to the above, but don't complete "WITH" again. */
2822 static const char *const list_CREATEROLE_WITH[] =
2823 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2824 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2825 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2826 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2827 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2828 "VALID UNTIL", NULL};
2830 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2833 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2834 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2835 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2837 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2838 /* Complete CREATE VIEW <name> with AS */
2839 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2840 COMPLETE_WITH_CONST("AS");
2841 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2842 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2843 COMPLETE_WITH_CONST("SELECT");
2845 /* CREATE MATERIALIZED VIEW */
2846 else if (Matches2("CREATE", "MATERIALIZED"))
2847 COMPLETE_WITH_CONST("VIEW");
2848 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2849 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2850 COMPLETE_WITH_CONST("AS");
2851 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2852 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2853 COMPLETE_WITH_CONST("SELECT");
2855 /* CREATE EVENT TRIGGER */
2856 else if (Matches2("CREATE", "EVENT"))
2857 COMPLETE_WITH_CONST("TRIGGER");
2858 /* Complete CREATE EVENT TRIGGER <name> with ON */
2859 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2860 COMPLETE_WITH_CONST("ON");
2861 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2862 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2863 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2866 else if (Matches1("DEALLOCATE"))
2867 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2870 else if (Matches2("DECLARE", MatchAny))
2871 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2873 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2874 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2876 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2877 /* ... despite which, only complete DELETE with FROM at start of line */
2878 else if (Matches1("DELETE"))
2879 COMPLETE_WITH_CONST("FROM");
2880 /* Complete DELETE FROM with a list of tables */
2881 else if (TailMatches2("DELETE", "FROM"))
2882 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2883 /* Complete DELETE FROM <table> */
2884 else if (TailMatches3("DELETE", "FROM", MatchAny))
2885 COMPLETE_WITH_LIST2("USING", "WHERE");
2886 /* XXX: implement tab completion for DELETE ... USING */
2889 else if (Matches1("DISCARD"))
2890 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2893 else if (Matches1("DO"))
2894 COMPLETE_WITH_CONST("LANGUAGE");
2897 /* Complete DROP object with CASCADE / RESTRICT */
2898 else if (Matches3("DROP",
2899 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|STATISTICS|TABLE|TYPE|VIEW",
2901 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2902 (Matches4("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, MatchAny) &&
2903 ends_with(prev_wd, ')')) ||
2904 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2905 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2906 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2907 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2908 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2910 /* help completing some of the variants */
2911 else if (Matches3("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny))
2912 COMPLETE_WITH_CONST("(");
2913 else if (Matches4("DROP", "AGGREGATE|FUNCTION|PROCEDURE|ROUTINE", MatchAny, "("))
2914 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2915 else if (Matches2("DROP", "FOREIGN"))
2916 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2919 else if (Matches2("DROP", "INDEX"))
2920 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2921 " UNION SELECT 'CONCURRENTLY'");
2922 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2923 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2924 else if (Matches3("DROP", "INDEX", MatchAny))
2925 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2926 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2927 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2929 /* DROP MATERIALIZED VIEW */
2930 else if (Matches2("DROP", "MATERIALIZED"))
2931 COMPLETE_WITH_CONST("VIEW");
2932 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2933 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2936 else if (Matches2("DROP", "OWNED"))
2937 COMPLETE_WITH_CONST("BY");
2938 else if (Matches3("DROP", "OWNED", "BY"))
2939 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2941 /* DROP TEXT SEARCH */
2942 else if (Matches3("DROP", "TEXT", "SEARCH"))
2943 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2946 else if (Matches3("DROP", "TRIGGER", MatchAny))
2947 COMPLETE_WITH_CONST("ON");
2948 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2950 completion_info_charp = prev2_wd;
2951 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2953 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2954 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2956 /* DROP ACCESS METHOD */
2957 else if (Matches2("DROP", "ACCESS"))
2958 COMPLETE_WITH_CONST("METHOD");
2959 else if (Matches3("DROP", "ACCESS", "METHOD"))
2960 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2962 /* DROP EVENT TRIGGER */
2963 else if (Matches2("DROP", "EVENT"))
2964 COMPLETE_WITH_CONST("TRIGGER");
2965 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2966 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2968 /* DROP POLICY <name> */
2969 else if (Matches2("DROP", "POLICY"))
2970 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2971 /* DROP POLICY <name> ON */
2972 else if (Matches3("DROP", "POLICY", MatchAny))
2973 COMPLETE_WITH_CONST("ON");
2974 /* DROP POLICY <name> ON <table> */
2975 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2977 completion_info_charp = prev2_wd;
2978 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2982 else if (Matches3("DROP", "RULE", MatchAny))
2983 COMPLETE_WITH_CONST("ON");
2984 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2986 completion_info_charp = prev2_wd;
2987 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2989 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2990 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2993 else if (Matches1("EXECUTE"))
2994 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2999 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
3001 else if (Matches1("EXPLAIN"))
3002 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
3003 "ANALYZE", "VERBOSE");
3004 else if (Matches2("EXPLAIN", "ANALYZE"))
3005 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
3007 else if (Matches2("EXPLAIN", "VERBOSE") ||
3008 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
3009 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
3012 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
3013 else if (Matches1("FETCH|MOVE"))
3014 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
3015 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
3016 else if (Matches2("FETCH|MOVE", MatchAny))
3017 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
3020 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
3021 * but we may as well tab-complete both: perhaps some users prefer one
3022 * variant or the other.
3024 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
3025 COMPLETE_WITH_LIST2("FROM", "IN");
3027 /* FOREIGN DATA WRAPPER */
3028 /* applies in ALTER/DROP FDW and in CREATE SERVER */
3029 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
3030 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
3031 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3032 /* applies in CREATE SERVER */
3033 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
3034 HeadMatches2("CREATE", "SERVER"))
3035 COMPLETE_WITH_CONST("OPTIONS");
3038 else if (TailMatches2("FOREIGN", "TABLE") &&
3039 !TailMatches3("CREATE", MatchAny, MatchAny))
3040 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3042 /* FOREIGN SERVER */
3043 else if (TailMatches2("FOREIGN", "SERVER"))
3044 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3047 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
3048 * ALTER DEFAULT PRIVILEGES, so use TailMatches
3050 /* Complete GRANT/REVOKE with a list of roles and privileges */
3051 else if (TailMatches1("GRANT|REVOKE"))
3054 * With ALTER DEFAULT PRIVILEGES, restrict completion to grantable
3055 * privileges (can't grant roles)
3057 if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
3058 COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
3059 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
3060 "EXECUTE", "USAGE", "ALL");
3062 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3063 " UNION SELECT 'SELECT'"
3064 " UNION SELECT 'INSERT'"
3065 " UNION SELECT 'UPDATE'"
3066 " UNION SELECT 'DELETE'"
3067 " UNION SELECT 'TRUNCATE'"
3068 " UNION SELECT 'REFERENCES'"
3069 " UNION SELECT 'TRIGGER'"
3070 " UNION SELECT 'CREATE'"
3071 " UNION SELECT 'CONNECT'"
3072 " UNION SELECT 'TEMPORARY'"
3073 " UNION SELECT 'EXECUTE'"
3074 " UNION SELECT 'USAGE'"
3075 " UNION SELECT 'ALL'");
3079 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
3082 else if (TailMatches2("GRANT|REVOKE", MatchAny))
3084 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
3085 COMPLETE_WITH_CONST("ON");
3086 else if (TailMatches2("GRANT", MatchAny))
3087 COMPLETE_WITH_CONST("TO");
3089 COMPLETE_WITH_CONST("FROM");
3093 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
3096 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
3097 * result via UNION; seems to work intuitively.
3099 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
3100 * here will only work if the privilege list contains exactly one
3103 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
3106 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
3107 * objects supported.
3109 if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES"))
3110 COMPLETE_WITH_LIST7("TABLES", "SEQUENCES", "FUNCTIONS", "PROCEDURES", "ROUTINES", "TYPES", "SCHEMAS");
3112 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
3113 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
3114 " UNION SELECT 'ALL PROCEDURES IN SCHEMA'"
3115 " UNION SELECT 'ALL ROUTINES IN SCHEMA'"
3116 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
3117 " UNION SELECT 'ALL TABLES IN SCHEMA'"
3118 " UNION SELECT 'DATABASE'"
3119 " UNION SELECT 'DOMAIN'"
3120 " UNION SELECT 'FOREIGN DATA WRAPPER'"
3121 " UNION SELECT 'FOREIGN SERVER'"
3122 " UNION SELECT 'FUNCTION'"
3123 " UNION SELECT 'LANGUAGE'"
3124 " UNION SELECT 'LARGE OBJECT'"
3125 " UNION SELECT 'PROCEDURE'"
3126 " UNION SELECT 'ROUTINE'"
3127 " UNION SELECT 'SCHEMA'"
3128 " UNION SELECT 'SEQUENCE'"
3129 " UNION SELECT 'TABLE'"
3130 " UNION SELECT 'TABLESPACE'"
3131 " UNION SELECT 'TYPE'");
3133 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
3134 COMPLETE_WITH_LIST5("FUNCTIONS IN SCHEMA",
3135 "PROCEDURES IN SCHEMA",
3136 "ROUTINES IN SCHEMA",
3137 "SEQUENCES IN SCHEMA",
3138 "TABLES IN SCHEMA");
3139 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
3140 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
3143 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
3144 * appropriate objects.
3146 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
3148 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
3150 if (TailMatches1("DATABASE"))
3151 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3152 else if (TailMatches1("DOMAIN"))
3153 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3154 else if (TailMatches1("FUNCTION"))
3155 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3156 else if (TailMatches1("LANGUAGE"))
3157 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3158 else if (TailMatches1("PROCEDURE"))
3159 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_procedures, NULL);
3160 else if (TailMatches1("ROUTINE"))
3161 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
3162 else if (TailMatches1("SCHEMA"))
3163 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3164 else if (TailMatches1("SEQUENCE"))
3165 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3166 else if (TailMatches1("TABLE"))
3167 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3168 else if (TailMatches1("TABLESPACE"))
3169 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3170 else if (TailMatches1("TYPE"))
3171 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3172 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
3173 COMPLETE_WITH_CONST("TO");
3175 COMPLETE_WITH_CONST("FROM");
3179 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
3180 * CURRENT_USER, or SESSION_USER.
3182 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
3183 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
3184 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
3185 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
3186 else if (HeadMatches3("ALTER", "DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
3187 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
3188 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
3189 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
3190 COMPLETE_WITH_CONST("TO");
3191 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
3192 COMPLETE_WITH_CONST("FROM");
3194 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
3195 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
3197 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3198 COMPLETE_WITH_CONST("TO");
3200 COMPLETE_WITH_CONST("FROM");
3203 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
3204 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
3206 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3207 COMPLETE_WITH_CONST("TO");
3209 COMPLETE_WITH_CONST("FROM");
3212 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
3213 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
3215 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
3216 COMPLETE_WITH_CONST("TO");
3218 COMPLETE_WITH_CONST("FROM");
3222 else if (TailMatches3("FROM", MatchAny, "GROUP"))
3223 COMPLETE_WITH_CONST("BY");
3225 /* IMPORT FOREIGN SCHEMA */
3226 else if (Matches1("IMPORT"))
3227 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
3228 else if (Matches2("IMPORT", "FOREIGN"))
3229 COMPLETE_WITH_CONST("SCHEMA");
3231 /* INSERT --- can be inside EXPLAIN, RULE, etc */
3232 /* Complete INSERT with "INTO" */
3233 else if (TailMatches1("INSERT"))
3234 COMPLETE_WITH_CONST("INTO");
3235 /* Complete INSERT INTO with table names */
3236 else if (TailMatches2("INSERT", "INTO"))
3237 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3238 /* Complete "INSERT INTO <table> (" with attribute names */
3239 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
3240 COMPLETE_WITH_ATTR(prev2_wd, "");
3243 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
3244 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
3246 else if (TailMatches3("INSERT", "INTO", MatchAny))
3247 COMPLETE_WITH_LIST6("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
3250 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
3251 * "TABLE" or "OVERRIDING"
3253 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
3254 ends_with(prev_wd, ')'))
3255 COMPLETE_WITH_LIST4("SELECT", "TABLE", "VALUES", "OVERRIDING");
3257 /* Complete OVERRIDING */
3258 else if (TailMatches1("OVERRIDING"))
3259 COMPLETE_WITH_LIST2("SYSTEM VALUE", "USER VALUE");
3261 /* Complete after OVERRIDING clause */
3262 else if (TailMatches3("OVERRIDING", MatchAny, "VALUE"))
3263 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
3265 /* Insert an open parenthesis after "VALUES" */
3266 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
3267 COMPLETE_WITH_CONST("(");
3270 /* Complete LOCK [TABLE] with a list of tables */
3271 else if (Matches1("LOCK"))
3272 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
3273 " UNION SELECT 'TABLE'");
3274 else if (Matches2("LOCK", "TABLE"))
3275 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
3277 /* For the following, handle the case of a single table only for now */
3279 /* Complete LOCK [TABLE] <table> with "IN" */
3280 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
3281 Matches3("LOCK", "TABLE", MatchAny))
3282 COMPLETE_WITH_CONST("IN");
3284 /* Complete LOCK [TABLE] <table> IN with a lock mode */
3285 else if (Matches3("LOCK", MatchAny, "IN") ||
3286 Matches4("LOCK", "TABLE", MatchAny, "IN"))
3287 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
3288 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
3289 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
3290 "SHARE ROW EXCLUSIVE MODE",
3291 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
3293 /* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
3294 else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
3295 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
3296 COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
3298 /* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
3299 else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
3300 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
3301 COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
3302 "UPDATE EXCLUSIVE MODE");
3304 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
3305 else if (TailMatches1("NOTIFY"))
3306 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'");
3309 else if (TailMatches1("OPTIONS"))
3310 COMPLETE_WITH_CONST("(");
3312 /* OWNER TO - complete with available roles */
3313 else if (TailMatches2("OWNER", "TO"))
3314 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3317 else if (TailMatches3("FROM", MatchAny, "ORDER"))
3318 COMPLETE_WITH_CONST("BY");
3319 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
3320 COMPLETE_WITH_ATTR(prev3_wd, "");
3323 else if (Matches3("PREPARE", MatchAny, "AS"))
3324 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
3327 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
3328 * managers, not for manual use in interactive sessions.
3331 /* REASSIGN OWNED BY xxx TO yyy */
3332 else if (Matches1("REASSIGN"))
3333 COMPLETE_WITH_CONST("OWNED BY");
3334 else if (Matches2("REASSIGN", "OWNED"))
3335 COMPLETE_WITH_CONST("BY");
3336 else if (Matches3("REASSIGN", "OWNED", "BY"))
3337 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3338 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
3339 COMPLETE_WITH_CONST("TO");
3340 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
3341 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3343 /* REFRESH MATERIALIZED VIEW */
3344 else if (Matches1("REFRESH"))
3345 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
3346 else if (Matches2("REFRESH", "MATERIALIZED"))
3347 COMPLETE_WITH_CONST("VIEW");
3348 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
3349 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
3350 " UNION SELECT 'CONCURRENTLY'");
3351 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
3352 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3353 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
3354 COMPLETE_WITH_CONST("WITH");
3355 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
3356 COMPLETE_WITH_CONST("WITH");
3357 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
3358 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3359 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
3360 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3361 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
3362 COMPLETE_WITH_CONST("DATA");
3363 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
3364 COMPLETE_WITH_CONST("DATA");
3367 else if (Matches1("REINDEX"))
3368 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
3369 else if (Matches2("REINDEX", "TABLE"))
3370 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3371 else if (Matches2("REINDEX", "INDEX"))
3372 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3373 else if (Matches2("REINDEX", "SCHEMA"))
3374 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3375 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
3376 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3378 /* SECURITY LABEL */
3379 else if (Matches1("SECURITY"))
3380 COMPLETE_WITH_CONST("LABEL");
3381 else if (Matches2("SECURITY", "LABEL"))
3382 COMPLETE_WITH_LIST2("ON", "FOR");
3383 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
3384 COMPLETE_WITH_CONST("ON");
3385 else if (Matches3("SECURITY", "LABEL", "ON") ||
3386 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
3388 static const char *const list_SECURITY_LABEL[] =
3389 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
3390 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
3391 "MATERIALIZED VIEW", "LANGUAGE", "PUBLICATION", "PROCEDURE", "ROLE", "ROUTINE", "SCHEMA",
3392 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW", NULL};
3394 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
3396 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
3397 COMPLETE_WITH_CONST("IS");
3402 /* SET, RESET, SHOW */
3403 /* Complete with a variable name */
3404 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
3405 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
3406 else if (Matches1("SHOW"))
3407 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
3408 /* Complete "SET TRANSACTION" */
3409 else if (Matches2("SET", "TRANSACTION"))
3410 COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3411 else if (Matches2("BEGIN|START", "TRANSACTION") ||
3412 Matches2("BEGIN", "WORK") ||
3413 Matches1("BEGIN") ||
3414 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
3415 COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3416 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
3417 Matches2("BEGIN", "NOT") ||
3418 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
3419 COMPLETE_WITH_CONST("DEFERRABLE");
3420 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
3421 Matches2("BEGIN", "ISOLATION") ||
3422 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
3423 COMPLETE_WITH_CONST("LEVEL");
3424 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
3425 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
3426 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
3427 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
3428 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
3429 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
3430 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
3431 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
3432 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
3433 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
3434 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
3435 COMPLETE_WITH_CONST("READ");
3436 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
3437 Matches2("BEGIN", "READ") ||
3438 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
3439 COMPLETE_WITH_LIST2("ONLY", "WRITE");
3440 /* SET CONSTRAINTS */
3441 else if (Matches2("SET", "CONSTRAINTS"))
3442 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
3443 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
3444 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
3445 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
3446 /* Complete SET ROLE */
3447 else if (Matches2("SET", "ROLE"))
3448 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3449 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
3450 else if (Matches2("SET", "SESSION"))
3451 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
3452 /* Complete SET SESSION AUTHORIZATION with username */
3453 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
3454 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
3455 /* Complete RESET SESSION with AUTHORIZATION */
3456 else if (Matches2("RESET", "SESSION"))
3457 COMPLETE_WITH_CONST("AUTHORIZATION");
3458 /* Complete SET <var> with "TO" */
3459 else if (Matches2("SET", MatchAny))
3460 COMPLETE_WITH_CONST("TO");
3461 /* Complete ALTER DATABASE|FUNCTION||PROCEDURE|ROLE|ROUTINE|USER ... SET <name> */
3462 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|PROCEDURE|ROLE|ROUTINE|USER") &&
3463 TailMatches2("SET", MatchAny))
3464 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
3465 /* Suggest possible variable values */
3466 else if (TailMatches3("SET", MatchAny, "TO|="))
3468 /* special cased code for individual GUCs */
3469 if (TailMatches2("DateStyle", "TO|="))
3471 static const char *const my_list[] =
3472 {"ISO", "SQL", "Postgres", "German",
3473 "YMD", "DMY", "MDY",
3474 "US", "European", "NonEuropean",
3477 COMPLETE_WITH_LIST(my_list);
3479 else if (TailMatches2("search_path", "TO|="))
3480 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
3481 " AND nspname not like 'pg\\_toast%%' "
3482 " AND nspname not like 'pg\\_temp%%' "
3483 " UNION SELECT 'DEFAULT' ");
3486 /* generic, type based, GUC support */
3487 char *guctype = get_guctype(prev2_wd);
3489 if (guctype && strcmp(guctype, "enum") == 0)
3491 char querybuf[1024];
3493 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
3494 COMPLETE_WITH_QUERY(querybuf);
3496 else if (guctype && strcmp(guctype, "bool") == 0)
3497 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
3498 "1", "0", "DEFAULT");
3500 COMPLETE_WITH_CONST("DEFAULT");
3507 /* START TRANSACTION */
3508 else if (Matches1("START"))
3509 COMPLETE_WITH_CONST("TRANSACTION");
3511 /* TABLE, but not TABLE embedded in other commands */
3512 else if (Matches1("TABLE"))
3513 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3516 else if (TailMatches1("TABLESAMPLE"))
3517 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
3518 else if (TailMatches2("TABLESAMPLE", MatchAny))
3519 COMPLETE_WITH_CONST("(");
3522 else if (Matches1("TRUNCATE"))
3523 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3526 else if (Matches1("UNLISTEN"))
3527 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 '*'");
3529 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
3530 /* If prev. word is UPDATE suggest a list of tables */
3531 else if (TailMatches1("UPDATE"))
3532 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3533 /* Complete UPDATE <table> with "SET" */
3534 else if (TailMatches2("UPDATE", MatchAny))
3535 COMPLETE_WITH_CONST("SET");
3536 /* Complete UPDATE <table> SET with list of attributes */
3537 else if (TailMatches3("UPDATE", MatchAny, "SET"))
3538 COMPLETE_WITH_ATTR(prev2_wd, "");
3539 /* UPDATE <table> SET <attr> = */
3540 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
3541 COMPLETE_WITH_CONST("=");
3544 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
3545 COMPLETE_WITH_CONST("FOR");
3546 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
3547 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3548 " UNION SELECT 'CURRENT_USER'"
3549 " UNION SELECT 'PUBLIC'"
3550 " UNION SELECT 'USER'");
3551 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
3552 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3553 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
3554 COMPLETE_WITH_CONST("SERVER");
3555 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
3556 COMPLETE_WITH_CONST("OPTIONS");
3559 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
3560 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
3562 else if (Matches1("VACUUM"))
3563 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3564 " UNION SELECT 'FULL'"
3565 " UNION SELECT 'FREEZE'"
3566 " UNION SELECT 'ANALYZE'"
3567 " UNION SELECT 'VERBOSE'");
3568 else if (Matches2("VACUUM", "FULL|FREEZE"))
3569 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3570 " UNION SELECT 'ANALYZE'"
3571 " UNION SELECT 'VERBOSE'");
3572 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
3573 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3574 " UNION SELECT 'VERBOSE'");
3575 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
3576 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3577 " UNION SELECT 'ANALYZE'");
3578 else if (Matches2("VACUUM", "VERBOSE"))
3579 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3580 " UNION SELECT 'ANALYZE'");
3581 else if (Matches2("VACUUM", "ANALYZE"))
3582 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3583 " UNION SELECT 'VERBOSE'");
3584 else if (HeadMatches1("VACUUM"))
3585 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3587 /* WITH [RECURSIVE] */
3590 * Only match when WITH is the first word, as WITH may appear in many
3593 else if (Matches1("WITH"))
3594 COMPLETE_WITH_CONST("RECURSIVE");
3597 /* Complete with list of tables */
3598 else if (Matches1("ANALYZE"))
3599 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
3602 /* Simple case of the word before the where being the table name */
3603 else if (TailMatches2(MatchAny, "WHERE"))
3604 COMPLETE_WITH_ATTR(prev2_wd, "");
3607 /* TODO: also include SRF ? */
3608 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
3609 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3612 else if (TailMatches1("JOIN"))
3613 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3615 /* Backslash commands */
3616 /* TODO: \dc \dd \dl */
3617 else if (TailMatchesCS1("\\?"))
3618 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
3619 else if (TailMatchesCS1("\\connect|\\c"))
3621 if (!recognized_connection_string(text))
3622 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3624 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
3626 if (!recognized_connection_string(prev_wd))
3627 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3629 else if (TailMatchesCS1("\\da*"))
3630 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
3631 else if (TailMatchesCS1("\\dA*"))
3632 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3633 else if (TailMatchesCS1("\\db*"))
3634 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3635 else if (TailMatchesCS1("\\dD*"))
3636 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3637 else if (TailMatchesCS1("\\des*"))
3638 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3639 else if (TailMatchesCS1("\\deu*"))
3640 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3641 else if (TailMatchesCS1("\\dew*"))
3642 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3643 else if (TailMatchesCS1("\\df*"))
3644 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3646 else if (TailMatchesCS1("\\dFd*"))
3647 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
3648 else if (TailMatchesCS1("\\dFp*"))
3649 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
3650 else if (TailMatchesCS1("\\dFt*"))
3651 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
3652 /* must be at end of \dF alternatives: */
3653 else if (TailMatchesCS1("\\dF*"))
3654 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
3656 else if (TailMatchesCS1("\\di*"))
3657 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3658 else if (TailMatchesCS1("\\dL*"))
3659 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3660 else if (TailMatchesCS1("\\dn*"))
3661 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3662 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
3663 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3664 else if (TailMatchesCS1("\\ds*"))
3665 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3666 else if (TailMatchesCS1("\\dt*"))
3667 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3668 else if (TailMatchesCS1("\\dT*"))
3669 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3670 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
3671 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3672 else if (TailMatchesCS1("\\dv*"))
3673 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3674 else if (TailMatchesCS1("\\dx*"))
3675 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
3676 else if (TailMatchesCS1("\\dm*"))
3677 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3678 else if (TailMatchesCS1("\\dE*"))
3679 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3680 else if (TailMatchesCS1("\\dy*"))
3681 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3683 /* must be at end of \d alternatives: */
3684 else if (TailMatchesCS1("\\d*"))
3685 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3687 else if (TailMatchesCS1("\\ef"))
3688 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
3689 else if (TailMatchesCS1("\\ev"))
3690 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3692 else if (TailMatchesCS1("\\encoding"))
3693 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3694 else if (TailMatchesCS1("\\h|\\help"))
3695 COMPLETE_WITH_LIST(sql_commands);
3696 else if (TailMatchesCS2("\\h|\\help", MatchAny))
3698 if (TailMatches1("DROP"))
3699 matches = completion_matches(text, drop_command_generator);
3700 else if (TailMatches1("ALTER"))
3701 matches = completion_matches(text, alter_command_generator);
3704 * CREATE is recognized by tail match elsewhere, so doesn't need to be
3708 else if (TailMatchesCS3("\\h|\\help", MatchAny, MatchAny))
3710 if (TailMatches2("CREATE|DROP", "ACCESS"))
3711 COMPLETE_WITH_CONST("METHOD");
3712 else if (TailMatches2("ALTER", "DEFAULT"))
3713 COMPLETE_WITH_CONST("PRIVILEGES");
3714 else if (TailMatches2("CREATE|ALTER|DROP", "EVENT"))
3715 COMPLETE_WITH_CONST("TRIGGER");
3716 else if (TailMatches2("CREATE|ALTER|DROP", "FOREIGN"))
3717 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
3718 else if (TailMatches2("ALTER", "LARGE"))
3719 COMPLETE_WITH_CONST("OBJECT");
3720 else if (TailMatches2("CREATE|ALTER|DROP", "MATERIALIZED"))
3721 COMPLETE_WITH_CONST("VIEW");
3722 else if (TailMatches2("CREATE|ALTER|DROP", "TEXT"))
3723 COMPLETE_WITH_CONST("SEARCH");
3724 else if (TailMatches2("CREATE|ALTER|DROP", "USER"))
3725 COMPLETE_WITH_CONST("MAPPING FOR");
3727 else if (TailMatchesCS4("\\h|\\help", MatchAny, MatchAny, MatchAny))
3729 if (TailMatches3("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
3730 COMPLETE_WITH_CONST("WRAPPER");
3731 else if (TailMatches3("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
3732 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3733 else if (TailMatches3("CREATE|ALTER|DROP", "USER", "MAPPING"))
3734 COMPLETE_WITH_CONST("FOR");
3736 else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
3737 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3738 else if (TailMatchesCS1("\\password"))
3739 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3740 else if (TailMatchesCS1("\\pset"))
3742 static const char *const my_list[] =
3743 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3744 "footer", "format", "linestyle", "null", "numericlocale",
3745 "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3746 "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3747 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3749 COMPLETE_WITH_LIST_CS(my_list);
3751 else if (TailMatchesCS2("\\pset", MatchAny))
3753 if (TailMatchesCS1("format"))
3755 static const char *const my_list[] =
3756 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3757 "latex", "latex-longtable", "troff-ms", NULL};
3759 COMPLETE_WITH_LIST_CS(my_list);
3761 else if (TailMatchesCS1("linestyle"))
3762 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3763 else if (TailMatchesCS1("pager"))
3764 COMPLETE_WITH_LIST_CS3("on", "off", "always");
3765 else if (TailMatchesCS1("unicode_border_linestyle|"
3766 "unicode_column_linestyle|"
3767 "unicode_header_linestyle"))
3768 COMPLETE_WITH_LIST_CS2("single", "double");
3770 else if (TailMatchesCS1("\\unset"))
3771 matches = complete_from_variables(text, "", "", true);
3772 else if (TailMatchesCS1("\\set"))
3773 matches = complete_from_variables(text, "", "", false);
3774 else if (TailMatchesCS2("\\set", MatchAny))
3776 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3777 "SINGLELINE|SINGLESTEP"))
3778 COMPLETE_WITH_LIST_CS2("on", "off");
3779 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3780 COMPLETE_WITH_LIST_CS4("lower", "upper",
3781 "preserve-lower", "preserve-upper");
3782 else if (TailMatchesCS1("ECHO"))
3783 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3784 else if (TailMatchesCS1("ECHO_HIDDEN"))
3785 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3786 else if (TailMatchesCS1("HISTCONTROL"))
3787 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3788 "ignoreboth", "none");
3789 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3790 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3791 else if (TailMatchesCS1("SHOW_CONTEXT"))
3792 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3793 else if (TailMatchesCS1("VERBOSITY"))
3794 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3796 else if (TailMatchesCS1("\\sf*"))
3797 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
3798 else if (TailMatchesCS1("\\sv*"))
3799 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3800 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3801 "\\ir|\\include_relative|\\o|\\out|"
3802 "\\s|\\w|\\write|\\lo_import"))
3804 completion_charp = "\\";
3805 matches = completion_matches(text, complete_from_files);
3809 * Finally, we look through the list of "things", such as TABLE, INDEX and
3810 * check if that was the previous word. If so, execute the query to get a
3817 for (i = 0; words_after_create[i].name; i++)
3819 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3821 if (words_after_create[i].query)
3822 COMPLETE_WITH_QUERY(words_after_create[i].query);
3823 else if (words_after_create[i].vquery)
3824 COMPLETE_WITH_VERSIONED_QUERY(words_after_create[i].vquery);
3825 else if (words_after_create[i].squery)
3826 COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(words_after_create[i].squery,
3834 * If we still don't have anything to match we have to fabricate some sort
3835 * of default list. If we were to just return NULL, readline automatically
3836 * attempts filename completion, and that's usually no good.
3838 if (matches == NULL)
3840 COMPLETE_WITH_CONST("");
3841 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3842 rl_completion_append_character = '\0';
3847 free(previous_words);
3850 /* Return our Grand List O' Matches */
3856 * GENERATOR FUNCTIONS
3858 * These functions do all the actual work of completing the input. They get
3859 * passed the text so far and the count how many times they have been called
3860 * so far with the same text.
3861 * If you read the above carefully, you'll see that these don't get called
3862 * directly but through the readline interface.
3863 * The return value is expected to be the full completion of the text, going
3864 * through a list each time, or NULL if there are no more matches. The string
3865 * will be free()'d by readline, so you must run it through strdup() or
3866 * something of that sort.
3870 * Common routine for create_command_generator and drop_command_generator.
3871 * Entries that have 'excluded' flags are not returned.
3874 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3876 static int list_index,
3880 /* If this is the first time for this completion, init some values */
3884 string_length = strlen(text);
3887 /* find something that matches */
3888 while ((name = words_after_create[list_index++].name))
3890 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3891 !(words_after_create[list_index - 1].flags & excluded))
3892 return pg_strdup_keyword_case(name, text);
3894 /* if nothing matches, return NULL */
3899 * This one gives you one from a list of things you can put after CREATE
3903 create_command_generator(const char *text, int state)
3905 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3909 * This function gives you a list of things you can put after a DROP command.
3912 drop_command_generator(const char *text, int state)
3914 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3918 * This function gives you a list of things you can put after an ALTER command.
3921 alter_command_generator(const char *text, int state)
3923 return create_or_drop_command_generator(text, state, THING_NO_ALTER);
3927 * These functions generate lists using server queries.
3928 * They are all wrappers for _complete_from_query.
3932 complete_from_query(const char *text, int state)
3934 /* query is assumed to work for any server version */
3935 return _complete_from_query(completion_charp, NULL, text, state);
3939 complete_from_versioned_query(const char *text, int state)
3941 const VersionedQuery *vquery = completion_vquery;
3943 /* Find appropriate array element */
3944 while (pset.sversion < vquery->min_server_version)
3946 /* Fail completion if server is too old */
3947 if (vquery->query == NULL)
3950 return _complete_from_query(vquery->query, NULL, text, state);
3954 complete_from_schema_query(const char *text, int state)
3956 /* query is assumed to work for any server version */
3957 return _complete_from_query(completion_charp, completion_squery,
3962 complete_from_versioned_schema_query(const char *text, int state)
3964 const SchemaQuery *squery = completion_squery;
3965 const VersionedQuery *vquery = completion_vquery;
3967 /* Find appropriate array element */
3968 while (pset.sversion < squery->min_server_version)
3970 /* Fail completion if server is too old */
3971 if (squery->catname == NULL)
3974 /* Likewise for the add-on text, if any */
3977 while (pset.sversion < vquery->min_server_version)
3979 if (vquery->query == NULL)
3983 return _complete_from_query(vquery ? vquery->query : NULL,
3984 squery, text, state);
3989 * This creates a list of matching things, according to a query described by
3990 * the initial arguments. The caller has already done any work needed to
3991 * select the appropriate query for the server's version.
3993 * The query can be one of two kinds:
3995 * 1. A simple query which must contain a %d and a %s, which will be replaced
3996 * by the string length of the text and the text itself. The query may also
3997 * have up to four more %s in it; the first two such will be replaced by the
3998 * value of completion_info_charp, the next two by the value of
3999 * completion_info_charp2.
4001 * 2. A schema query used for completion of both schema and relation names.
4002 * These are more complex and must contain in the following order:
4003 * %d %s %d %s %d %s %s %d %s
4004 * where %d is the string length of the text and %s the text itself.
4006 * If both simple_query and schema_query are non-NULL, then we construct
4007 * a schema query and append the (uninterpreted) string simple_query to it.
4009 * It is assumed that strings should be escaped to become SQL literals
4010 * (that is, what is in the query is actually ... '%s' ...)
4012 * See top of file for examples of both kinds of query.
4014 * "text" and "state" are supplied by readline.
4017 _complete_from_query(const char *simple_query,
4018 const SchemaQuery *schema_query,
4019 const char *text, int state)
4021 static int list_index,
4023 static PGresult *result = NULL;
4026 * If this is the first time for this completion, we fetch a list of our
4027 * "things" from the backend.
4031 PQExpBufferData query_buffer;
4034 char *e_info_charp2;
4035 const char *pstr = text;
4036 int char_length = 0;
4039 byte_length = strlen(text);
4042 * Count length as number of characters (not bytes), for passing to
4048 pstr += PQmblen(pstr, pset.encoding);
4051 /* Free any prior result */
4055 /* Set up suitably-escaped copies of textual inputs */
4056 e_text = escape_string(text);
4058 if (completion_info_charp)
4059 e_info_charp = escape_string(completion_info_charp);
4061 e_info_charp = NULL;
4063 if (completion_info_charp2)
4064 e_info_charp2 = escape_string(completion_info_charp2);
4066 e_info_charp2 = NULL;
4068 initPQExpBuffer(&query_buffer);
4072 /* schema_query gives us the pieces to assemble */
4073 const char *qualresult = schema_query->qualresult;
4075 if (qualresult == NULL)
4076 qualresult = schema_query->result;
4078 /* Get unqualified names matching the input-so-far */
4079 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
4080 schema_query->result,
4081 schema_query->catname);
4082 if (schema_query->selcondition)
4083 appendPQExpBuffer(&query_buffer, "%s AND ",
4084 schema_query->selcondition);
4085 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
4086 schema_query->result,
4087 char_length, e_text);
4088 appendPQExpBuffer(&query_buffer, " AND %s",
4089 schema_query->viscondition);
4092 * When fetching relation names, suppress system catalogs unless
4093 * the input-so-far begins with "pg_". This is a compromise
4094 * between not offering system catalogs for completion at all, and
4095 * having them swamp the result when the input is just "p".
4097 if (strcmp(schema_query->catname,
4098 "pg_catalog.pg_class c") == 0 &&
4099 strncmp(text, "pg_", 3) !=0)
4101 appendPQExpBufferStr(&query_buffer,
4102 " AND c.relnamespace <> (SELECT oid FROM"
4103 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
4107 * Add in matching schema names, but only if there is more than
4108 * one potential match among schema names.
4110 appendPQExpBuffer(&query_buffer, "\nUNION\n"
4111 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
4112 "FROM pg_catalog.pg_namespace n "
4113 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
4114 char_length, e_text);
4115 appendPQExpBuffer(&query_buffer,
4116 " AND (SELECT pg_catalog.count(*)"
4117 " FROM pg_catalog.pg_namespace"
4118 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
4119 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
4120 char_length, e_text);
4123 * Add in matching qualified names, but only if there is exactly
4124 * one schema matching the input-so-far.
4126 appendPQExpBuffer(&query_buffer, "\nUNION\n"
4127 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
4128 "FROM %s, pg_catalog.pg_namespace n "
4129 "WHERE %s = n.oid AND ",
4131 schema_query->catname,
4132 schema_query->namespace);
4133 if (schema_query->selcondition)
4134 appendPQExpBuffer(&query_buffer, "%s AND ",
4135 schema_query->selcondition);
4136 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
4138 char_length, e_text);
4141 * This condition exploits the single-matching-schema rule to
4142 * speed up the query
4144 appendPQExpBuffer(&query_buffer,
4145 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
4146 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
4147 char_length, e_text);
4148 appendPQExpBuffer(&query_buffer,
4149 " AND (SELECT pg_catalog.count(*)"
4150 " FROM pg_catalog.pg_namespace"
4151 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
4152 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
4153 char_length, e_text);
4155 /* If an addon query was provided, use it */
4157 appendPQExpBuffer(&query_buffer, "\n%s", simple_query);
4161 Assert(simple_query);
4162 /* simple_query is an sprintf-style format string */
4163 appendPQExpBuffer(&query_buffer, simple_query,
4164 char_length, e_text,
4165 e_info_charp, e_info_charp,
4166 e_info_charp2, e_info_charp2);
4169 /* Limit the number of records in the result */
4170 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
4171 completion_max_records);
4173 result = exec_query(query_buffer.data);
4175 termPQExpBuffer(&query_buffer);
4180 free(e_info_charp2);
4183 /* Find something that matches */
4184 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
4188 while (list_index < PQntuples(result) &&
4189 (item = PQgetvalue(result, list_index++, 0)))
4190 if (pg_strncasecmp(text, item, byte_length) == 0)
4191 return pg_strdup(item);
4194 /* If nothing matches, free the db structure and return null */
4202 * This function returns in order one of a fixed, NULL pointer terminated list
4203 * of strings (if matching). This can be used if there are only a fixed number
4204 * SQL words that can appear at certain spot.
4207 complete_from_list(const char *text, int state)
4209 static int string_length,
4212 static bool casesensitive;
4215 /* need to have a list */
4216 Assert(completion_charpp != NULL);
4218 /* Initialization */
4222 string_length = strlen(text);
4223 casesensitive = completion_case_sensitive;
4227 while ((item = completion_charpp[list_index++]))
4229 /* First pass is case sensitive */
4230 if (casesensitive && strncmp(text, item, string_length) == 0)
4233 return pg_strdup(item);
4236 /* Second pass is case insensitive, don't bother counting matches */
4237 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
4239 if (completion_case_sensitive)
4240 return pg_strdup(item);
4244 * If case insensitive matching was requested initially,
4245 * adjust the case according to setting.
4247 return pg_strdup_keyword_case(item, text);
4252 * No matches found. If we're not case insensitive already, lets switch to
4253 * being case insensitive and try again
4255 if (casesensitive && matches == 0)
4257 casesensitive = false;
4260 return complete_from_list(text, state);
4263 /* If no more matches, return null. */
4269 * This function returns one fixed string the first time even if it doesn't
4270 * match what's there, and nothing the second time. This should be used if
4271 * there is only one possibility that can appear at a certain spot, so
4272 * misspellings will be overwritten. The string to be passed must be in
4276 complete_from_const(const char *text, int state)
4278 Assert(completion_charp != NULL);
4281 if (completion_case_sensitive)
4282 return pg_strdup(completion_charp);
4286 * If case insensitive matching was requested initially, adjust
4287 * the case according to setting.
4289 return pg_strdup_keyword_case(completion_charp, text);
4297 * This function appends the variable name with prefix and suffix to
4298 * the variable names array.
4301 append_variable_names(char ***varnames, int *nvars,
4302 int *maxvars, const char *varname,
4303 const char *prefix, const char *suffix)
4305 if (*nvars >= *maxvars)
4308 *varnames = (char **) pg_realloc(*varnames,
4309 ((*maxvars) + 1) * sizeof(char *));
4312 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
4317 * This function supports completion with the name of a psql variable.
4318 * The variable names can be prefixed and suffixed with additional text
4319 * to support quoting usages. If need_value is true, only variables
4320 * that are currently set are included; otherwise, special variables
4321 * (those that have hooks) are included even if currently unset.
4324 complete_from_variables(const char *text, const char *prefix, const char *suffix,
4332 struct _variable *ptr;
4334 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
4336 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
4338 if (need_value && !(ptr->value))
4340 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
4344 varnames[nvars] = NULL;
4345 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
4347 for (i = 0; i < nvars; i++)
4356 * This function wraps rl_filename_completion_function() to strip quotes from
4357 * the input before searching for matches and to quote any matches for which
4358 * the consuming command will require it.
4361 complete_from_files(const char *text, int state)
4363 static const char *unquoted_text;
4364 char *unquoted_match;
4369 /* Initialization: stash the unquoted input. */
4370 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
4371 false, true, pset.encoding);
4372 /* expect a NULL return for the empty string only */
4375 Assert(*text == '\0');
4376 unquoted_text = text;
4380 unquoted_match = filename_completion_function(unquoted_text, state);
4384 * Caller sets completion_charp to a zero- or one-character string
4385 * containing the escape character. This is necessary since \copy has
4386 * no escape character, but every other backslash command recognizes
4387 * "\" as an escape character. Since we have only two callers, don't
4388 * bother providing a macro to simplify this.
4390 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
4391 '\'', *completion_charp, pset.encoding);
4393 free(unquoted_match);
4395 ret = unquoted_match;
4402 /* HELPER FUNCTIONS */
4406 * Make a pg_strdup copy of s and convert the case according to
4407 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
4410 pg_strdup_keyword_case(const char *s, const char *ref)
4414 unsigned char first = ref[0];
4418 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
4419 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
4420 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
4421 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
4423 for (p = ret; *p; p++)
4424 *p = pg_tolower((unsigned char) *p);
4428 for (p = ret; *p; p++)
4429 *p = pg_toupper((unsigned char) *p);
4437 * escape_string - Escape argument for use as string literal.
4439 * The returned value has to be freed.
4442 escape_string(const char *text)
4447 text_length = strlen(text);
4449 result = pg_malloc(text_length * 2 + 1);
4450 PQescapeStringConn(pset.db, result, text, text_length, NULL);
4457 * Execute a query and report any errors. This should be the preferred way of
4458 * talking to the database in this file.
4461 exec_query(const char *query)
4465 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
4468 result = PQexec(pset.db, query);
4470 if (PQresultStatus(result) != PGRES_TUPLES_OK)
4473 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
4474 PQerrorMessage(pset.db), query);
4485 * Parse all the word(s) before point.
4487 * Returns a malloc'd array of character pointers that point into the malloc'd
4488 * data array returned to *buffer; caller must free() both of these when done.
4489 * *nwords receives the number of words found, ie, the valid length of the
4492 * Words are returned right to left, that is, previous_words[0] gets the last
4493 * word before point, previous_words[1] the next-to-last, etc.
4496 get_previous_words(int point, char **buffer, int *nwords)
4498 char **previous_words;
4501 int words_found = 0;
4505 * If we have anything in tab_completion_query_buf, paste it together with
4506 * rl_line_buffer to construct the full query. Otherwise we can just use
4507 * rl_line_buffer as the input string.
4509 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
4511 i = tab_completion_query_buf->len;
4512 buf = pg_malloc(point + i + 2);
4513 memcpy(buf, tab_completion_query_buf->data, i);
4515 memcpy(buf + i, rl_line_buffer, point);
4518 /* Readjust point to reference appropriate offset in buf */
4522 buf = rl_line_buffer;
4525 * Allocate an array of string pointers and a buffer to hold the strings
4526 * themselves. The worst case is that the line contains only
4527 * non-whitespace WORD_BREAKS characters, making each one a separate word.
4528 * This is usually much more space than we need, but it's cheaper than
4529 * doing a separate malloc() for each word.
4531 previous_words = (char **) pg_malloc(point * sizeof(char *));
4532 *buffer = outptr = (char *) pg_malloc(point * 2);
4535 * First we look for a non-word char before the current point. (This is
4536 * probably useless, if readline is on the same page as we are about what
4537 * is a word, but if so it's cheap.)
4539 for (i = point - 1; i >= 0; i--)
4541 if (strchr(WORD_BREAKS, buf[i]))
4547 * Now parse words, working backwards, until we hit start of line. The
4548 * backwards scan has some interesting but intentional properties
4549 * concerning parenthesis handling.
4555 bool inquotes = false;
4556 int parentheses = 0;
4558 /* now find the first non-space which then constitutes the end */
4560 for (i = point; i >= 0; i--)
4562 if (!isspace((unsigned char) buf[i]))
4568 /* if no end found, we're done */
4573 * Otherwise we now look for the start. The start is either the last
4574 * character before any word-break character going backwards from the
4575 * end, or it's simply character 0. We also handle open quotes and
4578 for (start = end; start > 0; start--)
4580 if (buf[start] == '"')
4581 inquotes = !inquotes;
4584 if (buf[start] == ')')
4586 else if (buf[start] == '(')
4588 if (--parentheses <= 0)
4591 else if (parentheses == 0 &&
4592 strchr(WORD_BREAKS, buf[start - 1]))
4597 /* Return the word located at start to end inclusive */
4598 previous_words[words_found++] = outptr;
4599 i = end - start + 1;
4600 memcpy(outptr, &buf[start], i);
4604 /* Continue searching */
4608 /* Release parsing input workspace, if we made one above */
4609 if (buf != rl_line_buffer)
4612 *nwords = words_found;
4613 return previous_words;
4617 * Look up the type for the GUC variable with the passed name.
4619 * Returns NULL if the variable is unknown. Otherwise the returned string,
4620 * containing the type, has to be freed.
4623 get_guctype(const char *varname)
4625 PQExpBufferData query_buffer;
4628 char *guctype = NULL;
4630 e_varname = escape_string(varname);
4632 initPQExpBuffer(&query_buffer);
4633 appendPQExpBuffer(&query_buffer,
4634 "SELECT vartype FROM pg_catalog.pg_settings "
4635 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
4638 result = exec_query(query_buffer.data);
4639 termPQExpBuffer(&query_buffer);
4642 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
4643 guctype = pg_strdup(PQgetvalue(result, 0, 0));
4653 * Surround a string with single quotes. This works for both SQL and
4654 * psql internal. Currently disabled because it is reported not to
4655 * cooperate with certain versions of readline.
4658 quote_file_name(char *text, int match_type, char *quote_pointer)
4663 (void) quote_pointer; /* not used */
4665 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
4666 s = pg_malloc(length);
4668 strcpy(s + 1, text);
4669 if (match_type == SINGLE_MATCH)
4670 s[length - 2] = '\'';
4671 s[length - 1] = '\0';
4676 dequote_file_name(char *text, char quote_char)
4682 return pg_strdup(text);
4684 length = strlen(text);
4685 s = pg_malloc(length - 2 + 1);
4686 strlcpy(s, text +1, length - 2 + 1);
4690 #endif /* NOT_USED */
4692 #endif /* USE_READLINE */