2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2017, PostgreSQL Global Development Group
6 * src/bin/psql/tab-complete.c
9 /*----------------------------------------------------------------------
10 * This file implements a somewhat more sophisticated readline "TAB
11 * completion" in psql. It is not intended to be AI, to replace
12 * learning SQL, or to relieve you from thinking about what you're
13 * doing. Also it does not always give you all the syntactically legal
14 * completions, only those that are the most common or the ones that
15 * the programmer felt most like implementing.
17 * CAVEAT: Tab completion causes queries to be sent to the backend.
18 * The number of tuples returned gets limited, in most default
19 * installations to 1000, but if you still don't like this prospect,
20 * you can turn off tab completion in your ~/.inputrc (or else
21 * ${INPUTRC}) file so:
24 * set disable-completion on
27 * See `man 3 readline' or `info readline' for the full details.
30 * - Quotes, parentheses, and other funny characters are not handled
31 * all that gracefully.
32 *----------------------------------------------------------------------
35 #include "postgres_fe.h"
36 #include "tab-complete.h"
39 /* If we don't have this, we might as well forget about the whole thing: */
44 #include "catalog/pg_class.h"
47 #include "pqexpbuffer.h"
50 #include "stringutils.h"
52 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
53 #define filename_completion_function rl_filename_completion_function
55 /* missing in some header files */
56 extern char *filename_completion_function();
59 #ifdef HAVE_RL_COMPLETION_MATCHES
60 #define completion_matches rl_completion_matches
63 /* word break characters */
64 #define WORD_BREAKS "\t\n@$><=;|&{() "
67 * Since readline doesn't let us pass any state through to the tab completion
68 * callback, we have to use this global variable to let get_previous_words()
69 * get at the previous lines of the current command. Ick.
71 PQExpBuffer tab_completion_query_buf = NULL;
74 * This struct is used to define "schema queries", which are custom-built
75 * to obtain possibly-schema-qualified names of database objects. There is
76 * enough similarity in the structure that we don't want to repeat it each
77 * time. So we put the components of each query into this struct and
78 * assemble them with the common boilerplate in _complete_from_query().
80 typedef struct SchemaQuery
83 * Name of catalog or catalogs to be queried, with alias, eg.
84 * "pg_catalog.pg_class c". Note that "pg_namespace n" will be added.
89 * Selection condition --- only rows meeting this condition are candidates
90 * to display. If catname mentions multiple tables, include the necessary
91 * join condition here. For example, this might look like "c.relkind = "
92 * CppAsString2(RELKIND_RELATION). Write NULL (not an empty string) if
95 const char *selcondition;
98 * Visibility condition --- which rows are visible without schema
99 * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
101 const char *viscondition;
104 * Namespace --- name of field to join to pg_namespace.oid. For example,
107 const char *namespace;
110 * Result --- the appropriately-quoted name to return, in the case of an
111 * unqualified name. For example, "pg_catalog.quote_ident(c.relname)".
116 * In some cases a different result must be used for qualified names.
117 * Enter that here, or write NULL if result can be used.
119 const char *qualresult;
123 /* Store maximum number of records we want from database queries
124 * (implemented via SELECT ... LIMIT xx).
126 static int completion_max_records;
129 * Communication variables set by COMPLETE_WITH_FOO macros and then used by
130 * the completion callback functions. Ugly but there is no better way.
132 static const char *completion_charp; /* to pass a string */
133 static const char *const * completion_charpp; /* to pass a list of strings */
134 static const char *completion_info_charp; /* to pass a second string */
135 static const char *completion_info_charp2; /* to pass a third string */
136 static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
137 static bool completion_case_sensitive; /* completion is case sensitive */
140 * A few macros to ease typing. You can use these to complete the given
142 * 1) The results from a query you pass it. (Perhaps one of those below?)
143 * 2) The results from a schema query you pass it.
144 * 3) The items from a null-pointer-terminated list (with or without
145 * case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
146 * 4) A string constant.
147 * 5) The list of attributes of the given table (possibly schema-qualified).
148 * 6/ The list of arguments to the given function (possibly schema-qualified).
150 #define COMPLETE_WITH_QUERY(query) \
152 completion_charp = query; \
153 matches = completion_matches(text, complete_from_query); \
156 #define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
158 completion_squery = &(query); \
159 completion_charp = addon; \
160 matches = completion_matches(text, complete_from_schema_query); \
163 #define COMPLETE_WITH_LIST_CS(list) \
165 completion_charpp = list; \
166 completion_case_sensitive = true; \
167 matches = completion_matches(text, complete_from_list); \
170 #define COMPLETE_WITH_LIST(list) \
172 completion_charpp = list; \
173 completion_case_sensitive = false; \
174 matches = completion_matches(text, complete_from_list); \
177 #define COMPLETE_WITH_CONST(string) \
179 completion_charp = string; \
180 completion_case_sensitive = false; \
181 matches = completion_matches(text, complete_from_const); \
184 #define COMPLETE_WITH_ATTR(relation, addon) \
186 char *_completion_schema; \
187 char *_completion_table; \
189 _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
190 false, false, pset.encoding); \
191 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
192 false, false, pset.encoding); \
193 _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
194 false, false, pset.encoding); \
195 if (_completion_table == NULL) \
197 completion_charp = Query_for_list_of_attributes addon; \
198 completion_info_charp = relation; \
202 completion_charp = Query_for_list_of_attributes_with_schema addon; \
203 completion_info_charp = _completion_table; \
204 completion_info_charp2 = _completion_schema; \
206 matches = completion_matches(text, complete_from_query); \
209 #define COMPLETE_WITH_ENUM_VALUE(type) \
211 char *_completion_schema; \
212 char *_completion_type; \
214 _completion_schema = strtokx(type, " \t\n\r", ".", "\"", 0, \
215 false, false, pset.encoding); \
216 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
217 false, false, pset.encoding); \
218 _completion_type = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
219 false, false, pset.encoding); \
220 if (_completion_type == NULL)\
222 completion_charp = Query_for_list_of_enum_values; \
223 completion_info_charp = type; \
227 completion_charp = Query_for_list_of_enum_values_with_schema; \
228 completion_info_charp = _completion_type; \
229 completion_info_charp2 = _completion_schema; \
231 matches = completion_matches(text, complete_from_query); \
234 #define COMPLETE_WITH_FUNCTION_ARG(function) \
236 char *_completion_schema; \
237 char *_completion_function; \
239 _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
240 false, false, pset.encoding); \
241 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
242 false, false, pset.encoding); \
243 _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
244 false, false, pset.encoding); \
245 if (_completion_function == NULL) \
247 completion_charp = Query_for_list_of_arguments; \
248 completion_info_charp = function; \
252 completion_charp = Query_for_list_of_arguments_with_schema; \
253 completion_info_charp = _completion_function; \
254 completion_info_charp2 = _completion_schema; \
256 matches = completion_matches(text, complete_from_query); \
260 * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
261 * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
263 #define COMPLETE_WITH_LIST2(s1, s2) \
265 static const char *const list[] = { s1, s2, NULL }; \
266 COMPLETE_WITH_LIST(list); \
269 #define COMPLETE_WITH_LIST3(s1, s2, s3) \
271 static const char *const list[] = { s1, s2, s3, NULL }; \
272 COMPLETE_WITH_LIST(list); \
275 #define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
277 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
278 COMPLETE_WITH_LIST(list); \
281 #define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
283 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
284 COMPLETE_WITH_LIST(list); \
287 #define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \
289 static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \
290 COMPLETE_WITH_LIST(list); \
293 #define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \
295 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \
296 COMPLETE_WITH_LIST(list); \
299 #define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \
301 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \
302 COMPLETE_WITH_LIST(list); \
305 #define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
307 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
308 COMPLETE_WITH_LIST(list); \
311 #define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
313 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
314 COMPLETE_WITH_LIST(list); \
318 * Likewise for COMPLETE_WITH_LIST_CS.
320 #define COMPLETE_WITH_LIST_CS2(s1, s2) \
322 static const char *const list[] = { s1, s2, NULL }; \
323 COMPLETE_WITH_LIST_CS(list); \
326 #define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
328 static const char *const list[] = { s1, s2, s3, NULL }; \
329 COMPLETE_WITH_LIST_CS(list); \
332 #define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
334 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
335 COMPLETE_WITH_LIST_CS(list); \
338 #define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
340 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
341 COMPLETE_WITH_LIST_CS(list); \
345 * Assembly instructions for schema queries
348 static const SchemaQuery Query_for_list_of_aggregates = {
350 "pg_catalog.pg_proc p",
354 "pg_catalog.pg_function_is_visible(p.oid)",
358 "pg_catalog.quote_ident(p.proname)",
363 static const SchemaQuery Query_for_list_of_datatypes = {
365 "pg_catalog.pg_type t",
366 /* selcondition --- ignore table rowtypes and array types */
368 " OR (SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
369 " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
370 "AND t.typname !~ '^_'",
372 "pg_catalog.pg_type_is_visible(t.oid)",
376 "pg_catalog.format_type(t.oid, NULL)",
378 "pg_catalog.quote_ident(t.typname)"
381 static const SchemaQuery Query_for_list_of_domains = {
383 "pg_catalog.pg_type t",
387 "pg_catalog.pg_type_is_visible(t.oid)",
391 "pg_catalog.quote_ident(t.typname)",
396 static const SchemaQuery Query_for_list_of_functions = {
398 "pg_catalog.pg_proc p",
402 "pg_catalog.pg_function_is_visible(p.oid)",
406 "pg_catalog.quote_ident(p.proname)",
411 static const SchemaQuery Query_for_list_of_indexes = {
413 "pg_catalog.pg_class c",
415 "c.relkind IN (" CppAsString2(RELKIND_INDEX) ")",
417 "pg_catalog.pg_table_is_visible(c.oid)",
421 "pg_catalog.quote_ident(c.relname)",
426 static const SchemaQuery Query_for_list_of_sequences = {
428 "pg_catalog.pg_class c",
430 "c.relkind IN (" CppAsString2(RELKIND_SEQUENCE) ")",
432 "pg_catalog.pg_table_is_visible(c.oid)",
436 "pg_catalog.quote_ident(c.relname)",
441 static const SchemaQuery Query_for_list_of_foreign_tables = {
443 "pg_catalog.pg_class c",
445 "c.relkind IN (" CppAsString2(RELKIND_FOREIGN_TABLE) ")",
447 "pg_catalog.pg_table_is_visible(c.oid)",
451 "pg_catalog.quote_ident(c.relname)",
456 static const SchemaQuery Query_for_list_of_tables = {
458 "pg_catalog.pg_class c",
460 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
461 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
463 "pg_catalog.pg_table_is_visible(c.oid)",
467 "pg_catalog.quote_ident(c.relname)",
472 static const SchemaQuery Query_for_list_of_partitioned_tables = {
474 "pg_catalog.pg_class c",
476 "c.relkind IN (" CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
478 "pg_catalog.pg_table_is_visible(c.oid)",
482 "pg_catalog.quote_ident(c.relname)",
487 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
489 "pg_catalog.pg_constraint c",
493 "true", /* there is no pg_constraint_is_visible */
497 "pg_catalog.quote_ident(c.conname)",
502 /* Relations supporting INSERT, UPDATE or DELETE */
503 static const SchemaQuery Query_for_list_of_updatables = {
505 "pg_catalog.pg_class c",
507 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
508 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
509 CppAsString2(RELKIND_VIEW) ", "
510 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
512 "pg_catalog.pg_table_is_visible(c.oid)",
516 "pg_catalog.quote_ident(c.relname)",
521 static const SchemaQuery Query_for_list_of_relations = {
523 "pg_catalog.pg_class c",
527 "pg_catalog.pg_table_is_visible(c.oid)",
531 "pg_catalog.quote_ident(c.relname)",
536 static const SchemaQuery Query_for_list_of_tsvmf = {
538 "pg_catalog.pg_class c",
540 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
541 CppAsString2(RELKIND_SEQUENCE) ", "
542 CppAsString2(RELKIND_VIEW) ", "
543 CppAsString2(RELKIND_MATVIEW) ", "
544 CppAsString2(RELKIND_FOREIGN_TABLE) ", "
545 CppAsString2(RELKIND_PARTITIONED_TABLE) ")",
547 "pg_catalog.pg_table_is_visible(c.oid)",
551 "pg_catalog.quote_ident(c.relname)",
556 static const SchemaQuery Query_for_list_of_tmf = {
558 "pg_catalog.pg_class c",
560 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
561 CppAsString2(RELKIND_MATVIEW) ", "
562 CppAsString2(RELKIND_FOREIGN_TABLE) ")",
564 "pg_catalog.pg_table_is_visible(c.oid)",
568 "pg_catalog.quote_ident(c.relname)",
573 static const SchemaQuery Query_for_list_of_tm = {
575 "pg_catalog.pg_class c",
577 "c.relkind IN (" CppAsString2(RELKIND_RELATION) ", "
578 CppAsString2(RELKIND_MATVIEW) ")",
580 "pg_catalog.pg_table_is_visible(c.oid)",
584 "pg_catalog.quote_ident(c.relname)",
589 static const SchemaQuery Query_for_list_of_views = {
591 "pg_catalog.pg_class c",
593 "c.relkind IN (" CppAsString2(RELKIND_VIEW) ")",
595 "pg_catalog.pg_table_is_visible(c.oid)",
599 "pg_catalog.quote_ident(c.relname)",
604 static const SchemaQuery Query_for_list_of_matviews = {
606 "pg_catalog.pg_class c",
608 "c.relkind IN (" CppAsString2(RELKIND_MATVIEW) ")",
610 "pg_catalog.pg_table_is_visible(c.oid)",
614 "pg_catalog.quote_ident(c.relname)",
621 * Queries to get lists of names of various kinds of things, possibly
622 * restricted to names matching a partially entered name. In these queries,
623 * the first %s will be replaced by the text entered so far (suitably escaped
624 * to become a SQL literal string). %d will be replaced by the length of the
625 * string (in unescaped form). A second and third %s, if present, will be
626 * replaced by a suitably-escaped version of the string provided in
627 * completion_info_charp. A fourth and fifth %s are similarly replaced by
628 * completion_info_charp2.
630 * Beware that the allowed sequences of %s and %d are determined by
631 * _complete_from_query().
634 #define Query_for_list_of_attributes \
635 "SELECT pg_catalog.quote_ident(attname) "\
636 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
637 " WHERE c.oid = a.attrelid "\
638 " AND a.attnum > 0 "\
639 " AND NOT a.attisdropped "\
640 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
641 " AND (pg_catalog.quote_ident(relname)='%s' "\
642 " OR '\"' || relname || '\"'='%s') "\
643 " AND pg_catalog.pg_table_is_visible(c.oid)"
645 #define Query_for_list_of_attributes_with_schema \
646 "SELECT pg_catalog.quote_ident(attname) "\
647 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
648 " WHERE c.oid = a.attrelid "\
649 " AND n.oid = c.relnamespace "\
650 " AND a.attnum > 0 "\
651 " AND NOT a.attisdropped "\
652 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
653 " AND (pg_catalog.quote_ident(relname)='%s' "\
654 " OR '\"' || relname || '\"' ='%s') "\
655 " AND (pg_catalog.quote_ident(nspname)='%s' "\
656 " OR '\"' || nspname || '\"' ='%s') "
658 #define Query_for_list_of_enum_values \
659 "SELECT pg_catalog.quote_literal(enumlabel) "\
660 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t "\
661 " WHERE t.oid = e.enumtypid "\
662 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
663 " AND (pg_catalog.quote_ident(typname)='%s' "\
664 " OR '\"' || typname || '\"'='%s') "\
665 " AND pg_catalog.pg_type_is_visible(t.oid)"
667 #define Query_for_list_of_enum_values_with_schema \
668 "SELECT pg_catalog.quote_literal(enumlabel) "\
669 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
670 " WHERE t.oid = e.enumtypid "\
671 " AND n.oid = t.typnamespace "\
672 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
673 " AND (pg_catalog.quote_ident(typname)='%s' "\
674 " OR '\"' || typname || '\"'='%s') "\
675 " AND (pg_catalog.quote_ident(nspname)='%s' "\
676 " OR '\"' || nspname || '\"' ='%s') "
678 #define Query_for_list_of_template_databases \
679 "SELECT pg_catalog.quote_ident(d.datname) "\
680 " FROM pg_catalog.pg_database d "\
681 " WHERE substring(pg_catalog.quote_ident(d.datname),1,%d)='%s' "\
682 " AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
684 #define Query_for_list_of_databases \
685 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
686 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
688 #define Query_for_list_of_tablespaces \
689 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
690 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
692 #define Query_for_list_of_encodings \
693 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
694 " FROM pg_catalog.pg_conversion "\
695 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
697 #define Query_for_list_of_languages \
698 "SELECT pg_catalog.quote_ident(lanname) "\
699 " FROM pg_catalog.pg_language "\
700 " WHERE lanname != 'internal' "\
701 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
703 #define Query_for_list_of_schemas \
704 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
705 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
707 #define Query_for_list_of_alter_system_set_vars \
709 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
710 " WHERE context != 'internal' "\
711 " UNION ALL SELECT 'all') ss "\
712 " WHERE substring(name,1,%d)='%s'"
714 #define Query_for_list_of_set_vars \
716 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
717 " WHERE context IN ('user', 'superuser') "\
718 " UNION ALL SELECT 'constraints' "\
719 " UNION ALL SELECT 'transaction' "\
720 " UNION ALL SELECT 'session' "\
721 " UNION ALL SELECT 'role' "\
722 " UNION ALL SELECT 'tablespace' "\
723 " UNION ALL SELECT 'all') ss "\
724 " WHERE substring(name,1,%d)='%s'"
726 #define Query_for_list_of_show_vars \
728 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
729 " UNION ALL SELECT 'session authorization' "\
730 " UNION ALL SELECT 'all') ss "\
731 " WHERE substring(name,1,%d)='%s'"
733 #define Query_for_list_of_roles \
734 " SELECT pg_catalog.quote_ident(rolname) "\
735 " FROM pg_catalog.pg_roles "\
736 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
738 #define Query_for_list_of_grant_roles \
739 " SELECT pg_catalog.quote_ident(rolname) "\
740 " FROM pg_catalog.pg_roles "\
741 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
742 " UNION ALL SELECT 'PUBLIC'"\
743 " UNION ALL SELECT 'CURRENT_USER'"\
744 " UNION ALL SELECT 'SESSION_USER'"
746 /* the silly-looking length condition is just to eat up the current word */
747 #define Query_for_table_owning_index \
748 "SELECT pg_catalog.quote_ident(c1.relname) "\
749 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
750 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
751 " and (%d = pg_catalog.length('%s'))"\
752 " and pg_catalog.quote_ident(c2.relname)='%s'"\
753 " and pg_catalog.pg_table_is_visible(c2.oid)"
755 /* the silly-looking length condition is just to eat up the current word */
756 #define Query_for_index_of_table \
757 "SELECT pg_catalog.quote_ident(c2.relname) "\
758 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
759 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
760 " and (%d = pg_catalog.length('%s'))"\
761 " and pg_catalog.quote_ident(c1.relname)='%s'"\
762 " and pg_catalog.pg_table_is_visible(c2.oid)"
764 /* the silly-looking length condition is just to eat up the current word */
765 #define Query_for_constraint_of_table \
766 "SELECT pg_catalog.quote_ident(conname) "\
767 " FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
768 " WHERE c1.oid=conrelid and (%d = pg_catalog.length('%s'))"\
769 " and pg_catalog.quote_ident(c1.relname)='%s'"\
770 " and pg_catalog.pg_table_is_visible(c1.oid)"
772 #define Query_for_all_table_constraints \
773 "SELECT pg_catalog.quote_ident(conname) "\
774 " FROM pg_catalog.pg_constraint c "\
775 " WHERE c.conrelid <> 0 "
777 /* the silly-looking length condition is just to eat up the current word */
778 #define Query_for_constraint_of_type \
779 "SELECT pg_catalog.quote_ident(conname) "\
780 " FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
781 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
782 " and pg_catalog.quote_ident(t.typname)='%s'"\
783 " and pg_catalog.pg_type_is_visible(t.oid)"
785 /* the silly-looking length condition is just to eat up the current word */
786 #define Query_for_list_of_tables_for_constraint \
787 "SELECT pg_catalog.quote_ident(relname) "\
788 " FROM pg_catalog.pg_class"\
789 " WHERE (%d = pg_catalog.length('%s'))"\
791 " (SELECT conrelid FROM pg_catalog.pg_constraint "\
792 " WHERE pg_catalog.quote_ident(conname)='%s')"
794 /* the silly-looking length condition is just to eat up the current word */
795 #define Query_for_rule_of_table \
796 "SELECT pg_catalog.quote_ident(rulename) "\
797 " FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
798 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
799 " and pg_catalog.quote_ident(c1.relname)='%s'"\
800 " and pg_catalog.pg_table_is_visible(c1.oid)"
802 /* the silly-looking length condition is just to eat up the current word */
803 #define Query_for_list_of_tables_for_rule \
804 "SELECT pg_catalog.quote_ident(relname) "\
805 " FROM pg_catalog.pg_class"\
806 " WHERE (%d = pg_catalog.length('%s'))"\
808 " (SELECT ev_class FROM pg_catalog.pg_rewrite "\
809 " WHERE pg_catalog.quote_ident(rulename)='%s')"
811 /* the silly-looking length condition is just to eat up the current word */
812 #define Query_for_trigger_of_table \
813 "SELECT pg_catalog.quote_ident(tgname) "\
814 " FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
815 " WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
816 " and pg_catalog.quote_ident(c1.relname)='%s'"\
817 " and pg_catalog.pg_table_is_visible(c1.oid)"\
818 " and not tgisinternal"
820 /* the silly-looking length condition is just to eat up the current word */
821 #define Query_for_list_of_tables_for_trigger \
822 "SELECT pg_catalog.quote_ident(relname) "\
823 " FROM pg_catalog.pg_class"\
824 " WHERE (%d = pg_catalog.length('%s'))"\
826 " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
827 " WHERE pg_catalog.quote_ident(tgname)='%s')"
829 #define Query_for_list_of_ts_configurations \
830 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
831 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
833 #define Query_for_list_of_ts_dictionaries \
834 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
835 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
837 #define Query_for_list_of_ts_parsers \
838 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
839 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
841 #define Query_for_list_of_ts_templates \
842 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
843 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
845 #define Query_for_list_of_fdws \
846 " SELECT pg_catalog.quote_ident(fdwname) "\
847 " FROM pg_catalog.pg_foreign_data_wrapper "\
848 " WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
850 #define Query_for_list_of_servers \
851 " SELECT pg_catalog.quote_ident(srvname) "\
852 " FROM pg_catalog.pg_foreign_server "\
853 " WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
855 #define Query_for_list_of_user_mappings \
856 " SELECT pg_catalog.quote_ident(usename) "\
857 " FROM pg_catalog.pg_user_mappings "\
858 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
860 #define Query_for_list_of_access_methods \
861 " SELECT pg_catalog.quote_ident(amname) "\
862 " FROM pg_catalog.pg_am "\
863 " WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
865 #define Query_for_list_of_publications \
866 " SELECT pg_catalog.quote_ident(pubname) "\
867 " FROM pg_catalog.pg_publication "\
868 " WHERE substring(pg_catalog.quote_ident(pubname),1,%d)='%s'"
870 #define Query_for_list_of_subscriptions \
871 " SELECT pg_catalog.quote_ident(s.subname) "\
872 " FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "\
873 " WHERE substring(pg_catalog.quote_ident(s.subname),1,%d)='%s' "\
874 " AND d.datname = pg_catalog.current_database() "\
875 " AND s.subdbid = d.oid"
877 /* the silly-looking length condition is just to eat up the current word */
878 #define Query_for_list_of_arguments \
879 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
880 " FROM pg_catalog.pg_proc "\
881 " WHERE (%d = pg_catalog.length('%s'))"\
882 " AND (pg_catalog.quote_ident(proname)='%s'"\
883 " OR '\"' || proname || '\"'='%s') "\
884 " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
886 /* the silly-looking length condition is just to eat up the current word */
887 #define Query_for_list_of_arguments_with_schema \
888 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
889 " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
890 " WHERE (%d = pg_catalog.length('%s'))"\
891 " AND n.oid = p.pronamespace "\
892 " AND (pg_catalog.quote_ident(proname)='%s' "\
893 " OR '\"' || proname || '\"' ='%s') "\
894 " AND (pg_catalog.quote_ident(nspname)='%s' "\
895 " OR '\"' || nspname || '\"' ='%s') "
897 #define Query_for_list_of_extensions \
898 " SELECT pg_catalog.quote_ident(extname) "\
899 " FROM pg_catalog.pg_extension "\
900 " WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
902 #define Query_for_list_of_available_extensions \
903 " SELECT pg_catalog.quote_ident(name) "\
904 " FROM pg_catalog.pg_available_extensions "\
905 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
907 /* the silly-looking length condition is just to eat up the current word */
908 #define Query_for_list_of_available_extension_versions \
909 " SELECT pg_catalog.quote_ident(version) "\
910 " FROM pg_catalog.pg_available_extension_versions "\
911 " WHERE (%d = pg_catalog.length('%s'))"\
912 " AND pg_catalog.quote_ident(name)='%s'"
914 /* the silly-looking length condition is just to eat up the current word */
915 #define Query_for_list_of_available_extension_versions_with_TO \
916 " SELECT 'TO ' || pg_catalog.quote_ident(version) "\
917 " FROM pg_catalog.pg_available_extension_versions "\
918 " WHERE (%d = pg_catalog.length('%s'))"\
919 " AND pg_catalog.quote_ident(name)='%s'"
921 #define Query_for_list_of_prepared_statements \
922 " SELECT pg_catalog.quote_ident(name) "\
923 " FROM pg_catalog.pg_prepared_statements "\
924 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
926 #define Query_for_list_of_event_triggers \
927 " SELECT pg_catalog.quote_ident(evtname) "\
928 " FROM pg_catalog.pg_event_trigger "\
929 " WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
931 #define Query_for_list_of_tablesample_methods \
932 " SELECT pg_catalog.quote_ident(proname) "\
933 " FROM pg_catalog.pg_proc "\
934 " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
935 " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
936 " substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
938 #define Query_for_list_of_policies \
939 " SELECT pg_catalog.quote_ident(polname) "\
940 " FROM pg_catalog.pg_policy "\
941 " WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
943 #define Query_for_list_of_tables_for_policy \
944 "SELECT pg_catalog.quote_ident(relname) "\
945 " FROM pg_catalog.pg_class"\
946 " WHERE (%d = pg_catalog.length('%s'))"\
948 " (SELECT polrelid FROM pg_catalog.pg_policy "\
949 " WHERE pg_catalog.quote_ident(polname)='%s')"
951 #define Query_for_enum \
952 " SELECT name FROM ( "\
953 " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
954 " FROM pg_catalog.pg_settings "\
955 " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
957 " SELECT 'DEFAULT' ) ss "\
958 " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
960 /* the silly-looking length condition is just to eat up the current word */
961 #define Query_for_partition_of_table \
962 "SELECT pg_catalog.quote_ident(c2.relname) "\
963 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i"\
964 " WHERE c1.oid=i.inhparent and i.inhrelid=c2.oid"\
965 " and (%d = pg_catalog.length('%s'))"\
966 " and pg_catalog.quote_ident(c1.relname)='%s'"\
967 " and pg_catalog.pg_table_is_visible(c2.oid)"\
968 " and c2.relispartition = 'true'"
971 * This is a list of all "things" in Pgsql, which can show up after CREATE or
972 * DROP; and there is also a query to get a list of them.
978 const char *query; /* simple query, or NULL */
979 const SchemaQuery *squery; /* schema query, or NULL */
980 const bits32 flags; /* visibility flags, see below */
983 #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
984 #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
985 #define THING_NO_ALTER (1 << 2) /* should not show up after ALTER */
986 #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP | THING_NO_ALTER)
988 static const pgsql_thing_t words_after_create[] = {
989 {"ACCESS METHOD", NULL, NULL, THING_NO_ALTER},
990 {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
991 {"CAST", NULL, NULL}, /* Casts have complex structures for names, so
993 {"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'"},
996 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
997 * to be used only by pg_dump.
999 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
1000 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
1001 {"DATABASE", Query_for_list_of_databases},
1002 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
1003 {"DEFAULT PRIVILEGES", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1004 {"DOMAIN", NULL, &Query_for_list_of_domains},
1005 {"EVENT TRIGGER", NULL, NULL},
1006 {"EXTENSION", Query_for_list_of_extensions},
1007 {"FOREIGN DATA WRAPPER", NULL, NULL},
1008 {"FOREIGN TABLE", NULL, NULL},
1009 {"FUNCTION", NULL, &Query_for_list_of_functions},
1010 {"GROUP", Query_for_list_of_roles},
1011 {"INDEX", NULL, &Query_for_list_of_indexes},
1012 {"LANGUAGE", Query_for_list_of_languages},
1013 {"LARGE OBJECT", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1014 {"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
1015 {"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a
1017 {"OWNED", NULL, NULL, THING_NO_CREATE | THING_NO_ALTER}, /* for DROP OWNED BY ... */
1018 {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
1019 {"POLICY", NULL, NULL},
1020 {"PUBLICATION", Query_for_list_of_publications},
1021 {"ROLE", Query_for_list_of_roles},
1022 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
1023 {"SCHEMA", Query_for_list_of_schemas},
1024 {"SEQUENCE", NULL, &Query_for_list_of_sequences},
1025 {"SERVER", Query_for_list_of_servers},
1026 {"SUBSCRIPTION", Query_for_list_of_subscriptions},
1027 {"SYSTEM", NULL, NULL, THING_NO_CREATE | THING_NO_DROP},
1028 {"TABLE", NULL, &Query_for_list_of_tables},
1029 {"TABLESPACE", Query_for_list_of_tablespaces},
1030 {"TEMP", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMP TABLE ... */
1031 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
1032 {"TEMPORARY", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE TEMPORARY TABLE ... */
1033 {"TEXT SEARCH", NULL, NULL},
1034 {"TRANSFORM", NULL, NULL},
1035 {"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"},
1036 {"TYPE", NULL, &Query_for_list_of_datatypes},
1037 {"UNIQUE", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNIQUE INDEX ... */
1038 {"UNLOGGED", NULL, NULL, THING_NO_DROP | THING_NO_ALTER}, /* for CREATE UNLOGGED TABLE
1040 {"USER", Query_for_list_of_roles},
1041 {"USER MAPPING FOR", NULL, NULL},
1042 {"VIEW", NULL, &Query_for_list_of_views},
1043 {NULL} /* end of list */
1047 /* Forward declaration of functions */
1048 static char **psql_completion(const char *text, int start, int end);
1049 static char *create_command_generator(const char *text, int state);
1050 static char *drop_command_generator(const char *text, int state);
1051 static char *alter_command_generator(const char *text, int state);
1052 static char *complete_from_query(const char *text, int state);
1053 static char *complete_from_schema_query(const char *text, int state);
1054 static char *_complete_from_query(int is_schema_query,
1055 const char *text, int state);
1056 static char *complete_from_list(const char *text, int state);
1057 static char *complete_from_const(const char *text, int state);
1058 static void append_variable_names(char ***varnames, int *nvars,
1059 int *maxvars, const char *varname,
1060 const char *prefix, const char *suffix);
1061 static char **complete_from_variables(const char *text,
1062 const char *prefix, const char *suffix, bool need_value);
1063 static char *complete_from_files(const char *text, int state);
1065 static char *pg_strdup_keyword_case(const char *s, const char *ref);
1066 static char *escape_string(const char *text);
1067 static PGresult *exec_query(const char *query);
1069 static char **get_previous_words(int point, char **buffer, int *nwords);
1071 static char *get_guctype(const char *varname);
1074 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
1075 static char *dequote_file_name(char *text, char quote_char);
1080 * Initialize the readline library for our purposes.
1083 initialize_readline(void)
1085 rl_readline_name = (char *) pset.progname;
1086 rl_attempted_completion_function = psql_completion;
1088 rl_basic_word_break_characters = WORD_BREAKS;
1090 completion_max_records = 1000;
1093 * There is a variable rl_completion_query_items for this but apparently
1094 * it's not defined everywhere.
1099 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1100 * using case-insensitive or case-sensitive comparisons.
1102 * If pattern is NULL, it's a wild card that matches any word.
1103 * If pattern begins with '!', the result is negated, ie we check that 'word'
1104 * does *not* match any alternative appearing in the rest of 'pattern'.
1105 * Any alternative can end with '*' which is a wild card, i.e., it means
1106 * match any word that matches the characters so far. (We do not currently
1107 * support '*' elsewhere than the end of an alternative.)
1109 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1110 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1111 * just be written directly in patterns.)
1113 #define MatchAny NULL
1114 #define MatchAnyExcept(pattern) ("!" pattern)
1117 word_matches_internal(const char *pattern,
1119 bool case_sensitive)
1124 /* NULL pattern matches anything. */
1125 if (pattern == NULL)
1128 /* Handle negated patterns from the MatchAnyExcept macro. */
1129 if (*pattern == '!')
1130 return !word_matches_internal(pattern + 1, word, case_sensitive);
1132 /* Else consider each alternative in the pattern. */
1133 wordlen = strlen(word);
1138 /* Find end of current alternative. */
1140 while (*c != '\0' && *c != '|')
1142 /* Was there a wild card? (Assumes first alternative is not empty) */
1145 /* Yes, wildcard match? */
1146 patternlen = c - pattern - 1;
1147 if (wordlen >= patternlen &&
1149 strncmp(word, pattern, patternlen) == 0 :
1150 pg_strncasecmp(word, pattern, patternlen) == 0))
1155 /* No, plain match? */
1156 patternlen = c - pattern;
1157 if (wordlen == patternlen &&
1159 strncmp(word, pattern, wordlen) == 0 :
1160 pg_strncasecmp(word, pattern, wordlen) == 0))
1163 /* Out of alternatives? */
1166 /* Nope, try next alternative. */
1174 * There are enough matching calls below that it seems worth having these two
1175 * interface routines rather than including a third parameter in every call.
1177 * word_matches --- match case-insensitively.
1180 word_matches(const char *pattern, const char *word)
1182 return word_matches_internal(pattern, word, false);
1186 * word_matches_cs --- match case-sensitively.
1189 word_matches_cs(const char *pattern, const char *word)
1191 return word_matches_internal(pattern, word, true);
1195 * Check if the final character of 's' is 'c'.
1198 ends_with(const char *s, char c)
1200 size_t length = strlen(s);
1202 return (length > 0 && s[length - 1] == c);
1206 * The completion function.
1208 * According to readline spec this gets passed the text entered so far and its
1209 * start and end positions in the readline buffer. The return value is some
1210 * partially obscure list format that can be generated by readline's
1211 * completion_matches() function, so we don't have to worry about it.
1214 psql_completion(const char *text, int start, int end)
1216 /* This is the variable we'll return. */
1217 char **matches = NULL;
1219 /* Workspace for parsed words. */
1222 /* This array will contain pointers to parsed words. */
1223 char **previous_words;
1225 /* The number of words found on the input line. */
1226 int previous_words_count;
1229 * For compactness, we use these macros to reference previous_words[].
1230 * Caution: do not access a previous_words[] entry without having checked
1231 * previous_words_count to be sure it's valid. In most cases below, that
1232 * check is implicit in a TailMatches() or similar macro, but in some
1233 * places we have to check it explicitly.
1235 #define prev_wd (previous_words[0])
1236 #define prev2_wd (previous_words[1])
1237 #define prev3_wd (previous_words[2])
1238 #define prev4_wd (previous_words[3])
1239 #define prev5_wd (previous_words[4])
1240 #define prev6_wd (previous_words[5])
1241 #define prev7_wd (previous_words[6])
1242 #define prev8_wd (previous_words[7])
1243 #define prev9_wd (previous_words[8])
1245 /* Macros for matching the last N words before point, case-insensitively. */
1246 #define TailMatches1(p1) \
1247 (previous_words_count >= 1 && \
1248 word_matches(p1, prev_wd))
1250 #define TailMatches2(p2, p1) \
1251 (previous_words_count >= 2 && \
1252 word_matches(p1, prev_wd) && \
1253 word_matches(p2, prev2_wd))
1255 #define TailMatches3(p3, p2, p1) \
1256 (previous_words_count >= 3 && \
1257 word_matches(p1, prev_wd) && \
1258 word_matches(p2, prev2_wd) && \
1259 word_matches(p3, prev3_wd))
1261 #define TailMatches4(p4, p3, p2, p1) \
1262 (previous_words_count >= 4 && \
1263 word_matches(p1, prev_wd) && \
1264 word_matches(p2, prev2_wd) && \
1265 word_matches(p3, prev3_wd) && \
1266 word_matches(p4, prev4_wd))
1268 #define TailMatches5(p5, p4, p3, p2, p1) \
1269 (previous_words_count >= 5 && \
1270 word_matches(p1, prev_wd) && \
1271 word_matches(p2, prev2_wd) && \
1272 word_matches(p3, prev3_wd) && \
1273 word_matches(p4, prev4_wd) && \
1274 word_matches(p5, prev5_wd))
1276 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1277 (previous_words_count >= 6 && \
1278 word_matches(p1, prev_wd) && \
1279 word_matches(p2, prev2_wd) && \
1280 word_matches(p3, prev3_wd) && \
1281 word_matches(p4, prev4_wd) && \
1282 word_matches(p5, prev5_wd) && \
1283 word_matches(p6, prev6_wd))
1285 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1286 (previous_words_count >= 7 && \
1287 word_matches(p1, prev_wd) && \
1288 word_matches(p2, prev2_wd) && \
1289 word_matches(p3, prev3_wd) && \
1290 word_matches(p4, prev4_wd) && \
1291 word_matches(p5, prev5_wd) && \
1292 word_matches(p6, prev6_wd) && \
1293 word_matches(p7, prev7_wd))
1295 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1296 (previous_words_count >= 8 && \
1297 word_matches(p1, prev_wd) && \
1298 word_matches(p2, prev2_wd) && \
1299 word_matches(p3, prev3_wd) && \
1300 word_matches(p4, prev4_wd) && \
1301 word_matches(p5, prev5_wd) && \
1302 word_matches(p6, prev6_wd) && \
1303 word_matches(p7, prev7_wd) && \
1304 word_matches(p8, prev8_wd))
1306 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1307 (previous_words_count >= 9 && \
1308 word_matches(p1, prev_wd) && \
1309 word_matches(p2, prev2_wd) && \
1310 word_matches(p3, prev3_wd) && \
1311 word_matches(p4, prev4_wd) && \
1312 word_matches(p5, prev5_wd) && \
1313 word_matches(p6, prev6_wd) && \
1314 word_matches(p7, prev7_wd) && \
1315 word_matches(p8, prev8_wd) && \
1316 word_matches(p9, prev9_wd))
1318 /* Macros for matching the last N words before point, case-sensitively. */
1319 #define TailMatchesCS1(p1) \
1320 (previous_words_count >= 1 && \
1321 word_matches_cs(p1, prev_wd))
1322 #define TailMatchesCS2(p2, p1) \
1323 (previous_words_count >= 2 && \
1324 word_matches_cs(p1, prev_wd) && \
1325 word_matches_cs(p2, prev2_wd))
1326 #define TailMatchesCS3(p3, p2, p1) \
1327 (previous_words_count >= 3 && \
1328 word_matches_cs(p1, prev_wd) && \
1329 word_matches_cs(p2, prev2_wd) && \
1330 word_matches_cs(p3, prev3_wd))
1331 #define TailMatchesCS4(p4, p3, p2, p1) \
1332 (previous_words_count >= 4 && \
1333 word_matches_cs(p1, prev_wd) && \
1334 word_matches_cs(p2, prev2_wd) && \
1335 word_matches_cs(p3, prev3_wd) && \
1336 word_matches_cs(p4, prev4_wd))
1339 * Macros for matching N words beginning at the start of the line,
1340 * case-insensitively.
1342 #define Matches1(p1) \
1343 (previous_words_count == 1 && \
1345 #define Matches2(p1, p2) \
1346 (previous_words_count == 2 && \
1347 TailMatches2(p1, p2))
1348 #define Matches3(p1, p2, p3) \
1349 (previous_words_count == 3 && \
1350 TailMatches3(p1, p2, p3))
1351 #define Matches4(p1, p2, p3, p4) \
1352 (previous_words_count == 4 && \
1353 TailMatches4(p1, p2, p3, p4))
1354 #define Matches5(p1, p2, p3, p4, p5) \
1355 (previous_words_count == 5 && \
1356 TailMatches5(p1, p2, p3, p4, p5))
1357 #define Matches6(p1, p2, p3, p4, p5, p6) \
1358 (previous_words_count == 6 && \
1359 TailMatches6(p1, p2, p3, p4, p5, p6))
1360 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1361 (previous_words_count == 7 && \
1362 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1363 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1364 (previous_words_count == 8 && \
1365 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1366 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1367 (previous_words_count == 9 && \
1368 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1371 * Macros for matching N words at the start of the line, regardless of
1372 * what is after them, case-insensitively.
1374 #define HeadMatches1(p1) \
1375 (previous_words_count >= 1 && \
1376 word_matches(p1, previous_words[previous_words_count - 1]))
1378 #define HeadMatches2(p1, p2) \
1379 (previous_words_count >= 2 && \
1380 word_matches(p1, previous_words[previous_words_count - 1]) && \
1381 word_matches(p2, previous_words[previous_words_count - 2]))
1383 #define HeadMatches3(p1, p2, p3) \
1384 (previous_words_count >= 3 && \
1385 word_matches(p1, previous_words[previous_words_count - 1]) && \
1386 word_matches(p2, previous_words[previous_words_count - 2]) && \
1387 word_matches(p3, previous_words[previous_words_count - 3]))
1389 /* Known command-starting keywords. */
1390 static const char *const sql_commands[] = {
1391 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
1392 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1393 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1394 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1395 "MOVE", "NOTIFY", "PREPARE",
1396 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1397 "RESET", "REVOKE", "ROLLBACK",
1398 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1399 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1403 /* psql's backslash commands. */
1404 static const char *const backslash_commands[] = {
1405 "\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1406 "\\copyright", "\\crosstabview",
1407 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1408 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1409 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1410 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
1411 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1412 "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
1413 "\\f", "\\g", "\\gexec", "\\gset", "\\gx", "\\h", "\\help", "\\H",
1414 "\\i", "\\ir", "\\l", "\\lo_import", "\\lo_export", "\\lo_list",
1415 "\\lo_unlink", "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q",
1416 "\\qecho", "\\r", "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t",
1417 "\\T", "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!",
1421 (void) end; /* "end" is not used */
1423 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1424 rl_completion_append_character = ' ';
1427 /* Clear a few things. */
1428 completion_charp = NULL;
1429 completion_charpp = NULL;
1430 completion_info_charp = NULL;
1431 completion_info_charp2 = NULL;
1434 * Scan the input line to extract the words before our current position.
1435 * According to those we'll make some smart decisions on what the user is
1436 * probably intending to type.
1438 previous_words = get_previous_words(start,
1440 &previous_words_count);
1442 /* If current word is a backslash command, offer completions for that */
1443 if (text[0] == '\\')
1444 COMPLETE_WITH_LIST_CS(backslash_commands);
1446 /* If current word is a variable interpolation, handle that case */
1447 else if (text[0] == ':' && text[1] != ':')
1449 if (text[1] == '\'')
1450 matches = complete_from_variables(text, ":'", "'", true);
1451 else if (text[1] == '"')
1452 matches = complete_from_variables(text, ":\"", "\"", true);
1454 matches = complete_from_variables(text, ":", "", true);
1457 /* If no previous word, suggest one of the basic sql commands */
1458 else if (previous_words_count == 0)
1459 COMPLETE_WITH_LIST(sql_commands);
1462 /* complete with something you can create */
1463 else if (TailMatches1("CREATE"))
1464 matches = completion_matches(text, create_command_generator);
1466 /* DROP, but not DROP embedded in other commands */
1467 /* complete with something you can drop */
1468 else if (Matches1("DROP"))
1469 matches = completion_matches(text, drop_command_generator);
1474 else if (Matches2("ALTER", "TABLE"))
1475 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1476 "UNION SELECT 'ALL IN TABLESPACE'");
1478 /* ALTER something */
1479 else if (Matches1("ALTER"))
1480 matches = completion_matches(text, alter_command_generator);
1481 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1482 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1483 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1484 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1485 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1486 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1487 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1488 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1489 COMPLETE_WITH_CONST("SET TABLESPACE");
1490 /* ALTER AGGREGATE,FUNCTION <name> */
1491 else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1492 COMPLETE_WITH_CONST("(");
1493 /* ALTER AGGREGATE,FUNCTION <name> (...) */
1494 else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1496 if (ends_with(prev_wd, ')'))
1497 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1499 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1501 /* ALTER PUBLICATION <name> ...*/
1502 else if (Matches3("ALTER","PUBLICATION",MatchAny))
1504 COMPLETE_WITH_LIST6("WITH (", "ADD TABLE", "SET TABLE", "DROP TABLE",
1505 "OWNER TO", "RENAME TO");
1507 /* ALTER PUBLICATION <name> .. SET ( ... */
1508 else if (HeadMatches3("ALTER", "PUBLICATION",MatchAny) && TailMatches2("SET", "("))
1510 COMPLETE_WITH_CONST("publish");
1512 /* ALTER SUBSCRIPTION <name> ... */
1513 else if (Matches3("ALTER","SUBSCRIPTION",MatchAny))
1515 COMPLETE_WITH_LIST8("SET (", "CONNECTION", "SET PUBLICATION", "ENABLE",
1516 "DISABLE", "OWNER TO", "RENAME TO", "REFRESH PUBLICATION WITH (");
1518 /* ALTER SUBSCRIPTION <name> REFRESH PUBLICATION WITH ( ... */
1519 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
1520 TailMatches4("REFRESH", "PUBLICATION", "WITH", "("))
1522 COMPLETE_WITH_CONST("copy_data");
1524 /* ALTER SUBSCRIPTION <name> .. SET ( ... */
1525 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("SET", "("))
1527 COMPLETE_WITH_CONST("slot_name");
1529 /* ALTER SCHEMA <name> */
1530 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1531 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1533 /* ALTER COLLATION <name> */
1534 else if (Matches3("ALTER", "COLLATION", MatchAny))
1535 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1537 /* ALTER CONVERSION <name> */
1538 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1539 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1541 /* ALTER DATABASE <name> */
1542 else if (Matches3("ALTER", "DATABASE", MatchAny))
1543 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1544 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1545 "CONNECTION LIMIT");
1547 /* ALTER EVENT TRIGGER */
1548 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1549 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1551 /* ALTER EVENT TRIGGER <name> */
1552 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1553 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1555 /* ALTER EVENT TRIGGER <name> ENABLE */
1556 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1557 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1559 /* ALTER EXTENSION <name> */
1560 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1561 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1563 /* ALTER EXTENSION <name> UPDATE */
1564 else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
1566 completion_info_charp = prev2_wd;
1567 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
1570 /* ALTER EXTENSION <name> UPDATE TO */
1571 else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
1573 completion_info_charp = prev3_wd;
1574 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
1578 else if (Matches2("ALTER", "FOREIGN"))
1579 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1581 /* ALTER FOREIGN DATA WRAPPER <name> */
1582 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1583 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1585 /* ALTER FOREIGN TABLE <name> */
1586 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1588 static const char *const list_ALTER_FOREIGN_TABLE[] =
1589 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1590 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1591 "VALIDATE CONSTRAINT", NULL};
1593 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1597 else if (Matches2("ALTER", "INDEX"))
1598 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1599 "UNION SELECT 'ALL IN TABLESPACE'");
1600 /* ALTER INDEX <name> */
1601 else if (Matches3("ALTER", "INDEX", MatchAny))
1602 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1603 /* ALTER INDEX <name> SET */
1604 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1605 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1606 /* ALTER INDEX <name> RESET */
1607 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1608 COMPLETE_WITH_CONST("(");
1609 /* ALTER INDEX <foo> SET|RESET ( */
1610 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1611 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1612 "gin_pending_list_limit");
1613 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1614 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1615 "gin_pending_list_limit =");
1617 /* ALTER LANGUAGE <name> */
1618 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1619 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1621 /* ALTER LARGE OBJECT <oid> */
1622 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1623 COMPLETE_WITH_CONST("OWNER TO");
1625 /* ALTER MATERIALIZED VIEW */
1626 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1627 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1628 "UNION SELECT 'ALL IN TABLESPACE'");
1630 /* ALTER USER,ROLE <name> */
1631 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1632 !TailMatches2("USER", "MAPPING"))
1634 static const char *const list_ALTERUSER[] =
1635 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1636 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1637 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1638 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1639 "REPLICATION", "RESET", "SET", "SUPERUSER",
1640 "VALID UNTIL", "WITH", NULL};
1642 COMPLETE_WITH_LIST(list_ALTERUSER);
1645 /* ALTER USER,ROLE <name> WITH */
1646 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1648 /* Similar to the above, but don't complete "WITH" again. */
1649 static const char *const list_ALTERUSER_WITH[] =
1650 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1651 "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
1652 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1653 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1654 "REPLICATION", "RESET", "SET", "SUPERUSER",
1655 "VALID UNTIL", NULL};
1657 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1660 /* ALTER DEFAULT PRIVILEGES */
1661 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1662 COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
1663 /* ALTER DEFAULT PRIVILEGES FOR */
1664 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1665 COMPLETE_WITH_CONST("ROLE");
1666 /* ALTER DEFAULT PRIVILEGES IN */
1667 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1668 COMPLETE_WITH_CONST("SCHEMA");
1669 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1670 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1672 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
1673 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1674 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1676 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
1677 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1678 else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1680 COMPLETE_WITH_CONST("ROLE");
1681 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
1682 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1683 else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1684 MatchAny, "IN", "SCHEMA", MatchAny) ||
1685 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1686 MatchAny, "FOR", "ROLE|USER", MatchAny))
1687 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1688 /* ALTER DOMAIN <name> */
1689 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1690 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1691 "VALIDATE CONSTRAINT");
1692 /* ALTER DOMAIN <sth> DROP */
1693 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1694 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1695 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1696 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1698 completion_info_charp = prev3_wd;
1699 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1701 /* ALTER DOMAIN <sth> RENAME */
1702 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1703 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1704 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1705 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1706 COMPLETE_WITH_CONST("TO");
1708 /* ALTER DOMAIN <sth> SET */
1709 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1710 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1711 /* ALTER SEQUENCE <name> */
1712 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1714 static const char *const list_ALTERSEQUENCE[] =
1715 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1716 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1718 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1720 /* ALTER SEQUENCE <name> NO */
1721 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1722 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1723 /* ALTER SERVER <name> */
1724 else if (Matches3("ALTER", "SERVER", MatchAny))
1725 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1726 /* ALTER SERVER <name> VERSION <version> */
1727 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1728 COMPLETE_WITH_CONST("OPTIONS");
1729 /* ALTER SYSTEM SET, RESET, RESET ALL */
1730 else if (Matches2("ALTER", "SYSTEM"))
1731 COMPLETE_WITH_LIST2("SET", "RESET");
1732 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1733 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1734 else if (Matches4("ALTER", "SYSTEM", "SET", MatchAny))
1735 COMPLETE_WITH_CONST("TO");
1736 /* ALTER VIEW <name> */
1737 else if (Matches3("ALTER", "VIEW", MatchAny))
1738 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1740 /* ALTER MATERIALIZED VIEW <name> */
1741 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1742 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1745 /* ALTER POLICY <name> */
1746 else if (Matches2("ALTER", "POLICY"))
1747 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1748 /* ALTER POLICY <name> ON */
1749 else if (Matches3("ALTER", "POLICY", MatchAny))
1750 COMPLETE_WITH_CONST("ON");
1751 /* ALTER POLICY <name> ON <table> */
1752 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1754 completion_info_charp = prev2_wd;
1755 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1757 /* ALTER POLICY <name> ON <table> - show options */
1758 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1759 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1760 /* ALTER POLICY <name> ON <table> TO <role> */
1761 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1762 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1763 /* ALTER POLICY <name> ON <table> USING ( */
1764 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1765 COMPLETE_WITH_CONST("(");
1766 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1767 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1768 COMPLETE_WITH_CONST("(");
1770 /* ALTER RULE <name>, add ON */
1771 else if (Matches3("ALTER", "RULE", MatchAny))
1772 COMPLETE_WITH_CONST("ON");
1774 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1775 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1777 completion_info_charp = prev2_wd;
1778 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1781 /* ALTER RULE <name> ON <name> */
1782 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1783 COMPLETE_WITH_CONST("RENAME TO");
1785 /* ALTER TRIGGER <name>, add ON */
1786 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1787 COMPLETE_WITH_CONST("ON");
1789 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1791 completion_info_charp = prev2_wd;
1792 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1796 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1798 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1799 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1801 /* ALTER TRIGGER <name> ON <name> */
1802 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1803 COMPLETE_WITH_CONST("RENAME TO");
1806 * If we detect ALTER TABLE <name>, suggest sub commands
1808 else if (Matches3("ALTER", "TABLE", MatchAny))
1810 static const char *const list_ALTER2[] =
1811 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1812 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1813 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", "ATTACH PARTITION",
1814 "DETACH PARTITION", NULL};
1816 COMPLETE_WITH_LIST(list_ALTER2);
1818 /* ALTER TABLE xxx ENABLE */
1819 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1820 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1822 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1823 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1824 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1826 completion_info_charp = prev3_wd;
1827 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1829 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1831 completion_info_charp = prev4_wd;
1832 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1834 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1836 completion_info_charp = prev3_wd;
1837 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1839 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1841 completion_info_charp = prev4_wd;
1842 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1844 /* ALTER TABLE xxx INHERIT */
1845 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1846 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1847 /* ALTER TABLE xxx NO INHERIT */
1848 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1849 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1850 /* ALTER TABLE xxx DISABLE */
1851 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1852 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1853 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1855 completion_info_charp = prev3_wd;
1856 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1858 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1860 completion_info_charp = prev3_wd;
1861 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1864 /* ALTER TABLE xxx ALTER */
1865 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1866 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1868 /* ALTER TABLE xxx RENAME */
1869 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1870 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1871 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1872 COMPLETE_WITH_ATTR(prev3_wd, "");
1874 /* ALTER TABLE xxx RENAME yyy */
1875 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1876 COMPLETE_WITH_CONST("TO");
1878 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1879 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1880 COMPLETE_WITH_CONST("TO");
1882 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1883 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1884 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1885 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1886 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1887 COMPLETE_WITH_ATTR(prev3_wd, "");
1890 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1891 * provide list of constraints
1893 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1895 completion_info_charp = prev3_wd;
1896 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1898 /* ALTER TABLE ALTER [COLUMN] <foo> */
1899 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1900 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1901 COMPLETE_WITH_LIST6("TYPE", "SET", "RESET", "RESTART", "ADD", "DROP");
1902 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1903 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1904 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1905 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1906 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1907 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1908 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1909 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1910 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1911 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1912 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1913 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1914 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1915 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1916 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1917 COMPLETE_WITH_LIST3("DEFAULT", "IDENTITY", "NOT NULL");
1918 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1919 COMPLETE_WITH_CONST("ON");
1920 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1922 completion_info_charp = prev3_wd;
1923 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1925 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1926 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1927 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1931 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1934 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1935 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1936 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
1937 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
1938 COMPLETE_WITH_CONST("OIDS");
1939 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1940 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1941 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
1942 /* ALTER TABLE <foo> RESET */
1943 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
1944 COMPLETE_WITH_CONST("(");
1945 /* ALTER TABLE <foo> SET|RESET ( */
1946 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1948 static const char *const list_TABLEOPTIONS[] =
1950 "autovacuum_analyze_scale_factor",
1951 "autovacuum_analyze_threshold",
1952 "autovacuum_enabled",
1953 "autovacuum_freeze_max_age",
1954 "autovacuum_freeze_min_age",
1955 "autovacuum_freeze_table_age",
1956 "autovacuum_multixact_freeze_max_age",
1957 "autovacuum_multixact_freeze_min_age",
1958 "autovacuum_multixact_freeze_table_age",
1959 "autovacuum_vacuum_cost_delay",
1960 "autovacuum_vacuum_cost_limit",
1961 "autovacuum_vacuum_scale_factor",
1962 "autovacuum_vacuum_threshold",
1965 "log_autovacuum_min_duration",
1966 "toast.autovacuum_enabled",
1967 "toast.autovacuum_freeze_max_age",
1968 "toast.autovacuum_freeze_min_age",
1969 "toast.autovacuum_freeze_table_age",
1970 "toast.autovacuum_multixact_freeze_max_age",
1971 "toast.autovacuum_multixact_freeze_min_age",
1972 "toast.autovacuum_multixact_freeze_table_age",
1973 "toast.autovacuum_vacuum_cost_delay",
1974 "toast.autovacuum_vacuum_cost_limit",
1975 "toast.autovacuum_vacuum_scale_factor",
1976 "toast.autovacuum_vacuum_threshold",
1977 "toast.log_autovacuum_min_duration",
1978 "user_catalog_table",
1982 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
1984 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
1986 completion_info_charp = prev5_wd;
1987 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1989 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1990 COMPLETE_WITH_CONST("INDEX");
1991 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1992 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
1993 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
1994 COMPLETE_WITH_CONST("IDENTITY");
1996 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
1999 else if (Matches5("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
2000 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2001 /* Limited completion support for partition bound specification */
2002 else if (TailMatches3("ATTACH", "PARTITION", MatchAny))
2003 COMPLETE_WITH_CONST("FOR VALUES");
2004 else if (TailMatches2("FOR", "VALUES"))
2005 COMPLETE_WITH_LIST2("FROM (", "IN (");
2007 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
2008 * partitions of <foo>.
2010 else if (Matches5("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
2012 completion_info_charp = prev3_wd;
2013 COMPLETE_WITH_QUERY(Query_for_partition_of_table);
2016 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
2017 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
2018 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
2019 /* ALTER TABLESPACE <foo> SET|RESET */
2020 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
2021 COMPLETE_WITH_CONST("(");
2022 /* ALTER TABLESPACE <foo> SET|RESET ( */
2023 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
2024 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
2025 "effective_io_concurrency");
2027 /* ALTER TEXT SEARCH */
2028 else if (Matches3("ALTER", "TEXT", "SEARCH"))
2029 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2030 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
2031 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
2032 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
2033 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
2034 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2035 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
2037 "OWNER TO", "RENAME TO", "SET SCHEMA");
2039 /* complete ALTER TYPE <foo> with actions */
2040 else if (Matches3("ALTER", "TYPE", MatchAny))
2041 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
2043 "OWNER TO", "RENAME", "SET SCHEMA");
2044 /* complete ALTER TYPE <foo> ADD with actions */
2045 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
2046 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
2047 /* ALTER TYPE <foo> RENAME */
2048 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
2049 COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
2050 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
2051 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
2052 COMPLETE_WITH_CONST("TO");
2054 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
2057 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
2058 COMPLETE_WITH_ATTR(prev3_wd, "");
2059 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
2060 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
2061 COMPLETE_WITH_CONST("TYPE");
2062 /* complete ALTER GROUP <foo> */
2063 else if (Matches3("ALTER", "GROUP", MatchAny))
2064 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
2065 /* complete ALTER GROUP <foo> ADD|DROP with USER */
2066 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
2067 COMPLETE_WITH_CONST("USER");
2068 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
2069 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
2070 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2073 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
2075 else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
2076 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
2079 else if (Matches1("BEGIN"))
2080 COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2082 else if (Matches1("END|ABORT"))
2083 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
2085 else if (Matches1("COMMIT"))
2086 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
2087 /* RELEASE SAVEPOINT */
2088 else if (Matches1("RELEASE"))
2089 COMPLETE_WITH_CONST("SAVEPOINT");
2091 else if (Matches1("ROLLBACK"))
2092 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
2094 else if (Matches1("CLUSTER"))
2095 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
2096 else if (Matches2("CLUSTER", "VERBOSE"))
2097 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2098 /* If we have CLUSTER <sth>, then add "USING" */
2099 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
2100 COMPLETE_WITH_CONST("USING");
2101 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
2102 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
2103 COMPLETE_WITH_CONST("USING");
2104 /* If we have CLUSTER <sth> USING, then add the index as well */
2105 else if (Matches3("CLUSTER", MatchAny, "USING") ||
2106 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
2108 completion_info_charp = prev2_wd;
2109 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2113 else if (Matches1("COMMENT"))
2114 COMPLETE_WITH_CONST("ON");
2115 else if (Matches2("COMMENT", "ON"))
2117 static const char *const list_COMMENT[] =
2118 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
2119 "EVENT TRIGGER", "EXTENSION",
2120 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2121 "SERVER", "INDEX", "LANGUAGE", "POLICY", "PUBLICATION", "RULE", "SCHEMA", "SEQUENCE", "SUBSCRIPTION",
2122 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
2123 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
2124 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
2126 COMPLETE_WITH_LIST(list_COMMENT);
2128 else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
2129 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2130 else if (Matches3("COMMENT", "ON", "FOREIGN"))
2131 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2132 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
2133 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2134 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
2135 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
2136 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
2137 COMPLETE_WITH_CONST("ON");
2138 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2140 completion_info_charp = prev2_wd;
2141 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
2143 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
2144 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2145 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
2146 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2147 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
2148 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2149 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
2150 COMPLETE_WITH_CONST("IS");
2155 * If we have COPY, offer list of tables or "(" (Also cover the analogous
2156 * backslash command).
2158 else if (Matches1("COPY|\\copy"))
2159 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2160 " UNION ALL SELECT '('");
2161 /* If we have COPY BINARY, complete with list of tables */
2162 else if (Matches2("COPY", "BINARY"))
2163 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2164 /* If we have COPY (, complete it with legal commands */
2165 else if (Matches2("COPY|\\copy", "("))
2166 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
2167 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
2168 else if (Matches2("COPY|\\copy", MatchAny) ||
2169 Matches3("COPY", "BINARY", MatchAny))
2170 COMPLETE_WITH_LIST2("FROM", "TO");
2171 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
2172 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
2173 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
2175 completion_charp = "";
2176 matches = completion_matches(text, complete_from_files);
2179 /* Handle COPY [BINARY] <sth> FROM|TO filename */
2180 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
2181 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
2182 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
2185 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
2186 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
2187 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
2188 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
2191 /* CREATE ACCESS METHOD */
2192 /* Complete "CREATE ACCESS METHOD <name>" */
2193 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
2194 COMPLETE_WITH_CONST("TYPE");
2195 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
2196 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
2197 COMPLETE_WITH_CONST("INDEX");
2198 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
2199 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
2200 COMPLETE_WITH_CONST("HANDLER");
2202 /* CREATE DATABASE */
2203 else if (Matches3("CREATE", "DATABASE", MatchAny))
2204 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2206 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2207 "LC_COLLATE", "LC_CTYPE");
2209 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2210 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2212 /* CREATE EXTENSION */
2213 /* Complete with available extensions rather than installed ones. */
2214 else if (Matches2("CREATE", "EXTENSION"))
2215 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2216 /* CREATE EXTENSION <name> */
2217 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2218 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2219 /* CREATE EXTENSION <name> VERSION */
2220 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2222 completion_info_charp = prev2_wd;
2223 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2226 /* CREATE FOREIGN */
2227 else if (Matches2("CREATE", "FOREIGN"))
2228 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2230 /* CREATE FOREIGN DATA WRAPPER */
2231 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2232 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2234 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2235 /* First off we complete CREATE UNIQUE with "INDEX" */
2236 else if (TailMatches2("CREATE", "UNIQUE"))
2237 COMPLETE_WITH_CONST("INDEX");
2240 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2243 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2244 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2245 " UNION SELECT 'ON'"
2246 " UNION SELECT 'CONCURRENTLY'");
2247 /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
2248 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2249 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2250 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2253 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2256 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2257 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2258 " UNION SELECT 'ON'");
2259 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2260 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2261 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2262 COMPLETE_WITH_CONST("ON");
2265 * Complete INDEX <name> ON <table> with a list of table columns (which
2266 * should really be in parens)
2268 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2269 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2270 COMPLETE_WITH_LIST2("(", "USING");
2271 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2272 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2273 COMPLETE_WITH_ATTR(prev2_wd, "");
2274 /* same if you put in USING */
2275 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2276 COMPLETE_WITH_ATTR(prev4_wd, "");
2277 /* Complete USING with an index method */
2278 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2279 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2280 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2281 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2282 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2283 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2284 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2285 COMPLETE_WITH_CONST("(");
2288 /* Complete "CREATE POLICY <name> ON" */
2289 else if (Matches3("CREATE", "POLICY", MatchAny))
2290 COMPLETE_WITH_CONST("ON");
2291 /* Complete "CREATE POLICY <name> ON <table>" */
2292 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2293 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2294 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
2295 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2296 COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
2297 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
2298 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
2299 COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
2300 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR|TO|USING|WITH CHECK */
2301 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
2302 COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
2303 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2304 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2305 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2306 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2307 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2308 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2309 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2310 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2311 COMPLETE_WITH_LIST2("TO", "USING (");
2312 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2313 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2314 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2315 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2316 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2317 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2318 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2319 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2320 COMPLETE_WITH_CONST("(");
2321 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2322 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
2323 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2324 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR INSERT TO|WITH CHECK" */
2325 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
2326 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2327 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR SELECT|DELETE TO|USING" */
2328 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
2329 COMPLETE_WITH_LIST2("TO", "USING (");
2330 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR ALL|UPDATE TO|USING|WITH CHECK */
2331 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
2332 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2333 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO <role>" */
2334 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
2335 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2336 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE USING (" */
2337 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
2338 COMPLETE_WITH_CONST("(");
2341 /* CREATE PUBLICATION */
2342 else if (Matches3("CREATE", "PUBLICATION", MatchAny))
2343 COMPLETE_WITH_LIST3("FOR TABLE", "FOR ALL TABLES", "WITH (");
2344 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR"))
2345 COMPLETE_WITH_LIST2("TABLE", "ALL TABLES");
2346 /* Complete "CREATE PUBLICATION <name> FOR TABLE <table>" */
2347 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
2348 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2349 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
2350 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
2351 COMPLETE_WITH_CONST("publish");
2354 /* Complete "CREATE RULE <sth>" with "AS ON" */
2355 else if (Matches3("CREATE", "RULE", MatchAny))
2356 COMPLETE_WITH_CONST("AS ON");
2357 /* Complete "CREATE RULE <sth> AS" with "ON" */
2358 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2359 COMPLETE_WITH_CONST("ON");
2360 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2361 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2362 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2363 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2364 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2365 COMPLETE_WITH_CONST("TO");
2366 /* Complete "AS ON <sth> TO" with a table name */
2367 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2368 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2370 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2371 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2372 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2373 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2374 "CYCLE", "OWNED BY", "START WITH");
2375 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2376 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2377 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2379 /* CREATE SERVER <name> */
2380 else if (Matches3("CREATE", "SERVER", MatchAny))
2381 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2383 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2384 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2385 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2386 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2387 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2388 else if (TailMatches2("CREATE", "UNLOGGED"))
2389 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2390 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
2391 else if (TailMatches2("PARTITION", "BY"))
2392 COMPLETE_WITH_LIST2("RANGE (", "LIST (");
2393 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
2394 else if (TailMatches2("PARTITION", "OF"))
2395 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables, "");
2396 /* Limited completion support for partition bound specification */
2397 else if (TailMatches3("PARTITION", "OF", MatchAny))
2398 COMPLETE_WITH_CONST("FOR VALUES");
2400 /* CREATE TABLESPACE */
2401 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2402 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2403 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2404 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2405 COMPLETE_WITH_CONST("LOCATION");
2407 /* CREATE TEXT SEARCH */
2408 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2409 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2410 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2411 COMPLETE_WITH_CONST("(");
2413 /* CREATE SUBSCRIPTION */
2414 else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
2415 COMPLETE_WITH_CONST("CONNECTION");
2416 else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
2417 COMPLETE_WITH_CONST("PUBLICATION");
2418 else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
2419 MatchAny, "PUBLICATION"))
2421 /* complete with nothing here as this refers to remote publications */
2423 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("PUBLICATION", MatchAny))
2424 COMPLETE_WITH_CONST("WITH (");
2425 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
2426 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
2427 COMPLETE_WITH_LIST5("enabled", "create_slot", "slot_name",
2428 "copy_data", "connect");
2430 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2431 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2432 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2433 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2434 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2435 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2436 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2437 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2438 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2439 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2440 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2441 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2442 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2443 COMPLETE_WITH_LIST2("ON", "OR");
2446 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2449 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2450 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2451 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2452 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2453 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2454 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
2455 COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
2456 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2457 else if (HeadMatches2("CREATE", "TRIGGER") &&
2458 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
2459 COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2460 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
2461 COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
2462 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
2463 COMPLETE_WITH_CONST("AS");
2464 else if (HeadMatches2("CREATE", "TRIGGER") &&
2465 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
2466 TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
2467 COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2468 else if (HeadMatches2("CREATE", "TRIGGER") &&
2469 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
2470 TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
2471 COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2472 else if (HeadMatches2("CREATE", "TRIGGER") &&
2473 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2474 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2475 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
2476 TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
2477 COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
2478 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
2479 COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
2480 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
2481 COMPLETE_WITH_LIST2("ROW", "STATEMENT");
2482 else if (HeadMatches2("CREATE", "TRIGGER") &&
2483 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
2484 TailMatches2("FOR", "ROW|STATEMENT")))
2485 COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
2486 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2487 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2488 COMPLETE_WITH_CONST("PROCEDURE");
2489 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
2490 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2492 /* CREATE ROLE,USER,GROUP <name> */
2493 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2494 !TailMatches2("USER", "MAPPING"))
2496 static const char *const list_CREATEROLE[] =
2497 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2498 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2499 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2500 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2501 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2502 "VALID UNTIL", "WITH", NULL};
2504 COMPLETE_WITH_LIST(list_CREATEROLE);
2507 /* CREATE ROLE,USER,GROUP <name> WITH */
2508 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2510 /* Similar to the above, but don't complete "WITH" again. */
2511 static const char *const list_CREATEROLE_WITH[] =
2512 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2513 "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2514 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2515 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2516 "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
2517 "VALID UNTIL", NULL};
2519 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2522 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2523 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2524 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2526 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2527 /* Complete CREATE VIEW <name> with AS */
2528 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2529 COMPLETE_WITH_CONST("AS");
2530 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2531 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2532 COMPLETE_WITH_CONST("SELECT");
2534 /* CREATE MATERIALIZED VIEW */
2535 else if (Matches2("CREATE", "MATERIALIZED"))
2536 COMPLETE_WITH_CONST("VIEW");
2537 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2538 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2539 COMPLETE_WITH_CONST("AS");
2540 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2541 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2542 COMPLETE_WITH_CONST("SELECT");
2544 /* CREATE EVENT TRIGGER */
2545 else if (Matches2("CREATE", "EVENT"))
2546 COMPLETE_WITH_CONST("TRIGGER");
2547 /* Complete CREATE EVENT TRIGGER <name> with ON */
2548 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2549 COMPLETE_WITH_CONST("ON");
2550 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2551 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2552 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2555 else if (Matches1("DEALLOCATE"))
2556 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2559 else if (Matches2("DECLARE", MatchAny))
2560 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2562 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2563 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2565 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2566 /* ... despite which, only complete DELETE with FROM at start of line */
2567 else if (Matches1("DELETE"))
2568 COMPLETE_WITH_CONST("FROM");
2569 /* Complete DELETE FROM with a list of tables */
2570 else if (TailMatches2("DELETE", "FROM"))
2571 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2572 /* Complete DELETE FROM <table> */
2573 else if (TailMatches3("DELETE", "FROM", MatchAny))
2574 COMPLETE_WITH_LIST2("USING", "WHERE");
2575 /* XXX: implement tab completion for DELETE ... USING */
2578 else if (Matches1("DISCARD"))
2579 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2582 else if (Matches1("DO"))
2583 COMPLETE_WITH_CONST("LANGUAGE");
2586 /* Complete DROP object with CASCADE / RESTRICT */
2587 else if (Matches3("DROP",
2588 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|SUBSCRIPTION|TABLE|TYPE|VIEW",
2590 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2591 (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2592 ends_with(prev_wd, ')')) ||
2593 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2594 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2595 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2596 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2597 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2599 /* help completing some of the variants */
2600 else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2601 COMPLETE_WITH_CONST("(");
2602 else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2603 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2604 else if (Matches2("DROP", "FOREIGN"))
2605 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2608 else if (Matches2("DROP", "INDEX"))
2609 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2610 " UNION SELECT 'CONCURRENTLY'");
2611 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2612 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2613 else if (Matches3("DROP", "INDEX", MatchAny))
2614 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2615 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2616 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2618 /* DROP MATERIALIZED VIEW */
2619 else if (Matches2("DROP", "MATERIALIZED"))
2620 COMPLETE_WITH_CONST("VIEW");
2621 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2622 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2625 else if (Matches2("DROP", "OWNED"))
2626 COMPLETE_WITH_CONST("BY");
2627 else if (Matches3("DROP", "OWNED", "BY"))
2628 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2630 /* DROP TEXT SEARCH */
2631 else if (Matches3("DROP", "TEXT", "SEARCH"))
2632 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2635 else if (Matches3("DROP", "TRIGGER", MatchAny))
2636 COMPLETE_WITH_CONST("ON");
2637 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2639 completion_info_charp = prev2_wd;
2640 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2642 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2643 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2645 /* DROP ACCESS METHOD */
2646 else if (Matches2("DROP", "ACCESS"))
2647 COMPLETE_WITH_CONST("METHOD");
2648 else if (Matches3("DROP", "ACCESS", "METHOD"))
2649 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2651 /* DROP EVENT TRIGGER */
2652 else if (Matches2("DROP", "EVENT"))
2653 COMPLETE_WITH_CONST("TRIGGER");
2654 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2655 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2657 /* DROP POLICY <name> */
2658 else if (Matches2("DROP", "POLICY"))
2659 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2660 /* DROP POLICY <name> ON */
2661 else if (Matches3("DROP", "POLICY", MatchAny))
2662 COMPLETE_WITH_CONST("ON");
2663 /* DROP POLICY <name> ON <table> */
2664 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2666 completion_info_charp = prev2_wd;
2667 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2671 else if (Matches3("DROP", "RULE", MatchAny))
2672 COMPLETE_WITH_CONST("ON");
2673 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2675 completion_info_charp = prev2_wd;
2676 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2678 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2679 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2682 else if (Matches1("EXECUTE"))
2683 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2688 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2690 else if (Matches1("EXPLAIN"))
2691 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2692 "ANALYZE", "VERBOSE");
2693 else if (Matches2("EXPLAIN", "ANALYZE"))
2694 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2696 else if (Matches2("EXPLAIN", "VERBOSE") ||
2697 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2698 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2701 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2702 else if (Matches1("FETCH|MOVE"))
2703 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2704 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2705 else if (Matches2("FETCH|MOVE", MatchAny))
2706 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2709 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2710 * but we may as well tab-complete both: perhaps some users prefer one
2711 * variant or the other.
2713 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2714 COMPLETE_WITH_LIST2("FROM", "IN");
2716 /* FOREIGN DATA WRAPPER */
2717 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2718 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2719 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2720 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2721 /* applies in CREATE SERVER */
2722 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2723 HeadMatches2("CREATE", "SERVER"))
2724 COMPLETE_WITH_CONST("OPTIONS");
2727 else if (TailMatches2("FOREIGN", "TABLE") &&
2728 !TailMatches3("CREATE", MatchAny, MatchAny))
2729 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2731 /* FOREIGN SERVER */
2732 else if (TailMatches2("FOREIGN", "SERVER"))
2733 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2736 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
2737 * ALTER DEFAULT PRIVILEGES, so use TailMatches
2739 /* Complete GRANT/REVOKE with a list of roles and privileges */
2740 else if (TailMatches1("GRANT|REVOKE"))
2742 * With ALTER DEFAULT PRIVILEGES, restrict completion
2743 * to grantable privileges (can't grant roles)
2745 if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
2746 COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
2747 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
2748 "EXECUTE", "USAGE", "ALL");
2750 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2751 " UNION SELECT 'SELECT'"
2752 " UNION SELECT 'INSERT'"
2753 " UNION SELECT 'UPDATE'"
2754 " UNION SELECT 'DELETE'"
2755 " UNION SELECT 'TRUNCATE'"
2756 " UNION SELECT 'REFERENCES'"
2757 " UNION SELECT 'TRIGGER'"
2758 " UNION SELECT 'CREATE'"
2759 " UNION SELECT 'CONNECT'"
2760 " UNION SELECT 'TEMPORARY'"
2761 " UNION SELECT 'EXECUTE'"
2762 " UNION SELECT 'USAGE'"
2763 " UNION SELECT 'ALL'");
2766 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2769 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2771 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2772 COMPLETE_WITH_CONST("ON");
2773 else if (TailMatches2("GRANT", MatchAny))
2774 COMPLETE_WITH_CONST("TO");
2776 COMPLETE_WITH_CONST("FROM");
2780 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2783 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2784 * result via UNION; seems to work intuitively.
2786 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2787 * here will only work if the privilege list contains exactly one
2790 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2792 * With ALTER DEFAULT PRIVILEGES, restrict completion
2793 * to the kinds of objects supported.
2795 if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
2796 COMPLETE_WITH_LIST5("TABLES", "SEQUENCES", "FUNCTIONS", "TYPES", "SCHEMAS");
2798 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2799 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2800 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2801 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2802 " UNION SELECT 'DATABASE'"
2803 " UNION SELECT 'DOMAIN'"
2804 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2805 " UNION SELECT 'FOREIGN SERVER'"
2806 " UNION SELECT 'FUNCTION'"
2807 " UNION SELECT 'LANGUAGE'"
2808 " UNION SELECT 'LARGE OBJECT'"
2809 " UNION SELECT 'SCHEMA'"
2810 " UNION SELECT 'SEQUENCE'"
2811 " UNION SELECT 'TABLE'"
2812 " UNION SELECT 'TABLESPACE'"
2813 " UNION SELECT 'TYPE'");
2815 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2816 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2817 "TABLES IN SCHEMA");
2819 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2820 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2823 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2824 * appropriate objects.
2826 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2828 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2830 if (TailMatches1("DATABASE"))
2831 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2832 else if (TailMatches1("DOMAIN"))
2833 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2834 else if (TailMatches1("FUNCTION"))
2835 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2836 else if (TailMatches1("LANGUAGE"))
2837 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2838 else if (TailMatches1("SCHEMA"))
2839 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2840 else if (TailMatches1("SEQUENCE"))
2841 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2842 else if (TailMatches1("TABLE"))
2843 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2844 else if (TailMatches1("TABLESPACE"))
2845 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2846 else if (TailMatches1("TYPE"))
2847 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2848 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2849 COMPLETE_WITH_CONST("TO");
2851 COMPLETE_WITH_CONST("FROM");
2855 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2856 * CURRENT_USER, or SESSION_USER.
2858 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2859 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2860 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2861 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
2862 else if (HeadMatches3("ALTER","DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
2863 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2864 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2865 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2866 COMPLETE_WITH_CONST("TO");
2867 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2868 COMPLETE_WITH_CONST("FROM");
2870 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2871 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2873 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2874 COMPLETE_WITH_CONST("TO");
2876 COMPLETE_WITH_CONST("FROM");
2879 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2880 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2882 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2883 COMPLETE_WITH_CONST("TO");
2885 COMPLETE_WITH_CONST("FROM");
2888 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
2889 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
2891 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2892 COMPLETE_WITH_CONST("TO");
2894 COMPLETE_WITH_CONST("FROM");
2898 else if (TailMatches3("FROM", MatchAny, "GROUP"))
2899 COMPLETE_WITH_CONST("BY");
2901 /* IMPORT FOREIGN SCHEMA */
2902 else if (Matches1("IMPORT"))
2903 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
2904 else if (Matches2("IMPORT", "FOREIGN"))
2905 COMPLETE_WITH_CONST("SCHEMA");
2907 /* INSERT --- can be inside EXPLAIN, RULE, etc */
2908 /* Complete INSERT with "INTO" */
2909 else if (TailMatches1("INSERT"))
2910 COMPLETE_WITH_CONST("INTO");
2911 /* Complete INSERT INTO with table names */
2912 else if (TailMatches2("INSERT", "INTO"))
2913 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2914 /* Complete "INSERT INTO <table> (" with attribute names */
2915 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
2916 COMPLETE_WITH_ATTR(prev2_wd, "");
2919 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2920 * "TABLE" or "DEFAULT VALUES" or "OVERRIDING"
2922 else if (TailMatches3("INSERT", "INTO", MatchAny))
2923 COMPLETE_WITH_LIST6("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", "OVERRIDING");
2926 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
2927 * "TABLE" or "OVERRIDING"
2929 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
2930 ends_with(prev_wd, ')'))
2931 COMPLETE_WITH_LIST4("SELECT", "TABLE", "VALUES", "OVERRIDING");
2933 /* Complete OVERRIDING */
2934 else if (TailMatches1("OVERRIDING"))
2935 COMPLETE_WITH_LIST2("SYSTEM VALUE", "USER VALUE");
2937 /* Complete after OVERRIDING clause */
2938 else if (TailMatches3("OVERRIDING", MatchAny, "VALUE"))
2939 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
2941 /* Insert an open parenthesis after "VALUES" */
2942 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
2943 COMPLETE_WITH_CONST("(");
2946 /* Complete LOCK [TABLE] with a list of tables */
2947 else if (Matches1("LOCK"))
2948 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2949 " UNION SELECT 'TABLE'");
2950 else if (Matches2("LOCK", "TABLE"))
2951 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2953 /* For the following, handle the case of a single table only for now */
2955 /* Complete LOCK [TABLE] <table> with "IN" */
2956 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
2957 Matches3("LOCK", "TABLE", MatchAny))
2958 COMPLETE_WITH_CONST("IN");
2960 /* Complete LOCK [TABLE] <table> IN with a lock mode */
2961 else if (Matches3("LOCK", MatchAny, "IN") ||
2962 Matches4("LOCK", "TABLE", MatchAny, "IN"))
2963 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
2964 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
2965 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
2966 "SHARE ROW EXCLUSIVE MODE",
2967 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
2969 /* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
2970 else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
2971 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
2972 COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
2974 /* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
2975 else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
2976 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
2977 COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
2978 "UPDATE EXCLUSIVE MODE");
2980 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
2981 else if (TailMatches1("NOTIFY"))
2982 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'");
2985 else if (TailMatches1("OPTIONS"))
2986 COMPLETE_WITH_CONST("(");
2988 /* OWNER TO - complete with available roles */
2989 else if (TailMatches2("OWNER", "TO"))
2990 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2993 else if (TailMatches3("FROM", MatchAny, "ORDER"))
2994 COMPLETE_WITH_CONST("BY");
2995 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
2996 COMPLETE_WITH_ATTR(prev3_wd, "");
2999 else if (Matches3("PREPARE", MatchAny, "AS"))
3000 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
3003 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
3004 * managers, not for manual use in interactive sessions.
3007 /* REASSIGN OWNED BY xxx TO yyy */
3008 else if (Matches1("REASSIGN"))
3009 COMPLETE_WITH_CONST("OWNED BY");
3010 else if (Matches2("REASSIGN", "OWNED"))
3011 COMPLETE_WITH_CONST("BY");
3012 else if (Matches3("REASSIGN", "OWNED", "BY"))
3013 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3014 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
3015 COMPLETE_WITH_CONST("TO");
3016 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
3017 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3019 /* REFRESH MATERIALIZED VIEW */
3020 else if (Matches1("REFRESH"))
3021 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
3022 else if (Matches2("REFRESH", "MATERIALIZED"))
3023 COMPLETE_WITH_CONST("VIEW");
3024 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
3025 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
3026 " UNION SELECT 'CONCURRENTLY'");
3027 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
3028 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3029 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
3030 COMPLETE_WITH_CONST("WITH");
3031 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
3032 COMPLETE_WITH_CONST("WITH");
3033 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
3034 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3035 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
3036 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3037 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
3038 COMPLETE_WITH_CONST("DATA");
3039 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
3040 COMPLETE_WITH_CONST("DATA");
3043 else if (Matches1("REINDEX"))
3044 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
3045 else if (Matches2("REINDEX", "TABLE"))
3046 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3047 else if (Matches2("REINDEX", "INDEX"))
3048 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3049 else if (Matches2("REINDEX", "SCHEMA"))
3050 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3051 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
3052 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3054 /* SECURITY LABEL */
3055 else if (Matches1("SECURITY"))
3056 COMPLETE_WITH_CONST("LABEL");
3057 else if (Matches2("SECURITY", "LABEL"))
3058 COMPLETE_WITH_LIST2("ON", "FOR");
3059 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
3060 COMPLETE_WITH_CONST("ON");
3061 else if (Matches3("SECURITY", "LABEL", "ON") ||
3062 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
3064 static const char *const list_SECURITY_LABEL[] =
3065 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
3066 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
3067 "MATERIALIZED VIEW", "LANGUAGE", "PUBLICATION", "ROLE", "SCHEMA",
3068 "SEQUENCE", "SUBSCRIPTION", "TABLESPACE", "TYPE", "VIEW", NULL};
3070 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
3072 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
3073 COMPLETE_WITH_CONST("IS");
3078 /* SET, RESET, SHOW */
3079 /* Complete with a variable name */
3080 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
3081 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
3082 else if (Matches1("SHOW"))
3083 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
3084 /* Complete "SET TRANSACTION" */
3085 else if (Matches2("SET", "TRANSACTION"))
3086 COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3087 else if (Matches2("BEGIN|START", "TRANSACTION") ||
3088 Matches2("BEGIN", "WORK") ||
3089 Matches1("BEGIN") ||
3090 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
3091 COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3092 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
3093 Matches2("BEGIN", "NOT") ||
3094 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
3095 COMPLETE_WITH_CONST("DEFERRABLE");
3096 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
3097 Matches2("BEGIN", "ISOLATION") ||
3098 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
3099 COMPLETE_WITH_CONST("LEVEL");
3100 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
3101 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
3102 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
3103 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
3104 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
3105 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
3106 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
3107 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
3108 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
3109 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
3110 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
3111 COMPLETE_WITH_CONST("READ");
3112 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
3113 Matches2("BEGIN", "READ") ||
3114 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
3115 COMPLETE_WITH_LIST2("ONLY", "WRITE");
3116 /* SET CONSTRAINTS */
3117 else if (Matches2("SET", "CONSTRAINTS"))
3118 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
3119 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
3120 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
3121 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
3122 /* Complete SET ROLE */
3123 else if (Matches2("SET", "ROLE"))
3124 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3125 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
3126 else if (Matches2("SET", "SESSION"))
3127 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
3128 /* Complete SET SESSION AUTHORIZATION with username */
3129 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
3130 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
3131 /* Complete RESET SESSION with AUTHORIZATION */
3132 else if (Matches2("RESET", "SESSION"))
3133 COMPLETE_WITH_CONST("AUTHORIZATION");
3134 /* Complete SET <var> with "TO" */
3135 else if (Matches2("SET", MatchAny))
3136 COMPLETE_WITH_CONST("TO");
3137 /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
3138 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
3139 TailMatches2("SET", MatchAny))
3140 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
3141 /* Suggest possible variable values */
3142 else if (TailMatches3("SET", MatchAny, "TO|="))
3144 /* special cased code for individual GUCs */
3145 if (TailMatches2("DateStyle", "TO|="))
3147 static const char *const my_list[] =
3148 {"ISO", "SQL", "Postgres", "German",
3149 "YMD", "DMY", "MDY",
3150 "US", "European", "NonEuropean",
3153 COMPLETE_WITH_LIST(my_list);
3155 else if (TailMatches2("search_path", "TO|="))
3156 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
3157 " AND nspname not like 'pg\\_toast%%' "
3158 " AND nspname not like 'pg\\_temp%%' "
3159 " UNION SELECT 'DEFAULT' ");
3162 /* generic, type based, GUC support */
3163 char *guctype = get_guctype(prev2_wd);
3165 if (guctype && strcmp(guctype, "enum") == 0)
3167 char querybuf[1024];
3169 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
3170 COMPLETE_WITH_QUERY(querybuf);
3172 else if (guctype && strcmp(guctype, "bool") == 0)
3173 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
3174 "1", "0", "DEFAULT");
3176 COMPLETE_WITH_CONST("DEFAULT");
3183 /* START TRANSACTION */
3184 else if (Matches1("START"))
3185 COMPLETE_WITH_CONST("TRANSACTION");
3187 /* TABLE, but not TABLE embedded in other commands */
3188 else if (Matches1("TABLE"))
3189 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3192 else if (TailMatches1("TABLESAMPLE"))
3193 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
3194 else if (TailMatches2("TABLESAMPLE", MatchAny))
3195 COMPLETE_WITH_CONST("(");
3198 else if (Matches1("TRUNCATE"))
3199 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3202 else if (Matches1("UNLISTEN"))
3203 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 '*'");
3205 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
3206 /* If prev. word is UPDATE suggest a list of tables */
3207 else if (TailMatches1("UPDATE"))
3208 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3209 /* Complete UPDATE <table> with "SET" */
3210 else if (TailMatches2("UPDATE", MatchAny))
3211 COMPLETE_WITH_CONST("SET");
3212 /* Complete UPDATE <table> SET with list of attributes */
3213 else if (TailMatches3("UPDATE", MatchAny, "SET"))
3214 COMPLETE_WITH_ATTR(prev2_wd, "");
3215 /* UPDATE <table> SET <attr> = */
3216 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
3217 COMPLETE_WITH_CONST("=");
3220 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
3221 COMPLETE_WITH_CONST("FOR");
3222 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
3223 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3224 " UNION SELECT 'CURRENT_USER'"
3225 " UNION SELECT 'PUBLIC'"
3226 " UNION SELECT 'USER'");
3227 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
3228 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3229 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
3230 COMPLETE_WITH_CONST("SERVER");
3231 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
3232 COMPLETE_WITH_CONST("OPTIONS");
3235 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
3236 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
3238 else if (Matches1("VACUUM"))
3239 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3240 " UNION SELECT 'FULL'"
3241 " UNION SELECT 'FREEZE'"
3242 " UNION SELECT 'ANALYZE'"
3243 " UNION SELECT 'VERBOSE'");
3244 else if (Matches2("VACUUM", "FULL|FREEZE"))
3245 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3246 " UNION SELECT 'ANALYZE'"
3247 " UNION SELECT 'VERBOSE'");
3248 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
3249 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3250 " UNION SELECT 'VERBOSE'");
3251 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
3252 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3253 " UNION SELECT 'ANALYZE'");
3254 else if (Matches2("VACUUM", "VERBOSE"))
3255 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3256 " UNION SELECT 'ANALYZE'");
3257 else if (Matches2("VACUUM", "ANALYZE"))
3258 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3259 " UNION SELECT 'VERBOSE'");
3260 else if (HeadMatches1("VACUUM"))
3261 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3263 /* WITH [RECURSIVE] */
3266 * Only match when WITH is the first word, as WITH may appear in many
3269 else if (Matches1("WITH"))
3270 COMPLETE_WITH_CONST("RECURSIVE");
3273 /* Complete with list of tables */
3274 else if (Matches1("ANALYZE"))
3275 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
3278 /* Simple case of the word before the where being the table name */
3279 else if (TailMatches2(MatchAny, "WHERE"))
3280 COMPLETE_WITH_ATTR(prev2_wd, "");
3283 /* TODO: also include SRF ? */
3284 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
3285 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3288 else if (TailMatches1("JOIN"))
3289 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3291 /* Backslash commands */
3292 /* TODO: \dc \dd \dl */
3293 else if (TailMatchesCS1("\\?"))
3294 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
3295 else if (TailMatchesCS1("\\connect|\\c"))
3297 if (!recognized_connection_string(text))
3298 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3300 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
3302 if (!recognized_connection_string(prev_wd))
3303 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3305 else if (TailMatchesCS1("\\da*"))
3306 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
3307 else if (TailMatchesCS1("\\dA*"))
3308 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3309 else if (TailMatchesCS1("\\db*"))
3310 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3311 else if (TailMatchesCS1("\\dD*"))
3312 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3313 else if (TailMatchesCS1("\\des*"))
3314 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3315 else if (TailMatchesCS1("\\deu*"))
3316 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3317 else if (TailMatchesCS1("\\dew*"))
3318 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3319 else if (TailMatchesCS1("\\df*"))
3320 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3322 else if (TailMatchesCS1("\\dFd*"))
3323 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
3324 else if (TailMatchesCS1("\\dFp*"))
3325 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
3326 else if (TailMatchesCS1("\\dFt*"))
3327 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
3328 /* must be at end of \dF alternatives: */
3329 else if (TailMatchesCS1("\\dF*"))
3330 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
3332 else if (TailMatchesCS1("\\di*"))
3333 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3334 else if (TailMatchesCS1("\\dL*"))
3335 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3336 else if (TailMatchesCS1("\\dn*"))
3337 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3338 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
3339 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3340 else if (TailMatchesCS1("\\ds*"))
3341 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3342 else if (TailMatchesCS1("\\dt*"))
3343 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3344 else if (TailMatchesCS1("\\dT*"))
3345 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3346 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
3347 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3348 else if (TailMatchesCS1("\\dv*"))
3349 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3350 else if (TailMatchesCS1("\\dx*"))
3351 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
3352 else if (TailMatchesCS1("\\dm*"))
3353 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3354 else if (TailMatchesCS1("\\dE*"))
3355 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3356 else if (TailMatchesCS1("\\dy*"))
3357 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3359 /* must be at end of \d alternatives: */
3360 else if (TailMatchesCS1("\\d*"))
3361 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3363 else if (TailMatchesCS1("\\ef"))
3364 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3365 else if (TailMatchesCS1("\\ev"))
3366 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3368 else if (TailMatchesCS1("\\encoding"))
3369 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3370 else if (TailMatchesCS1("\\h|\\help"))
3371 COMPLETE_WITH_LIST(sql_commands);
3372 else if (TailMatchesCS2("\\h|\\help", MatchAny))
3374 if (TailMatches1("DROP"))
3375 matches = completion_matches(text, drop_command_generator);
3376 else if (TailMatches1("ALTER"))
3377 matches = completion_matches(text, alter_command_generator);
3378 /* CREATE is recognized by tail match elsewhere, so doesn't need to be
3381 else if (TailMatchesCS3("\\h|\\help", MatchAny, MatchAny))
3383 if (TailMatches2("CREATE|DROP", "ACCESS"))
3384 COMPLETE_WITH_CONST("METHOD");
3385 else if (TailMatches2("ALTER", "DEFAULT"))
3386 COMPLETE_WITH_CONST("PRIVILEGES");
3387 else if (TailMatches2("CREATE|ALTER|DROP", "EVENT"))
3388 COMPLETE_WITH_CONST("TRIGGER");
3389 else if (TailMatches2("CREATE|ALTER|DROP", "FOREIGN"))
3390 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
3391 else if (TailMatches2("ALTER", "LARGE"))
3392 COMPLETE_WITH_CONST("OBJECT");
3393 else if (TailMatches2("CREATE|ALTER|DROP", "MATERIALIZED"))
3394 COMPLETE_WITH_CONST("VIEW");
3395 else if (TailMatches2("CREATE|ALTER|DROP", "TEXT"))
3396 COMPLETE_WITH_CONST("SEARCH");
3397 else if (TailMatches2("CREATE|ALTER|DROP", "USER"))
3398 COMPLETE_WITH_CONST("MAPPING FOR");
3400 else if (TailMatchesCS4("\\h|\\help", MatchAny, MatchAny, MatchAny))
3402 if (TailMatches3("CREATE|ALTER|DROP", "FOREIGN", "DATA"))
3403 COMPLETE_WITH_CONST("WRAPPER");
3404 else if (TailMatches3("CREATE|ALTER|DROP", "TEXT", "SEARCH"))
3405 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
3406 else if (TailMatches3("CREATE|ALTER|DROP", "USER", "MAPPING"))
3407 COMPLETE_WITH_CONST("FOR");
3409 else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
3410 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3411 else if (TailMatchesCS1("\\password"))
3412 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3413 else if (TailMatchesCS1("\\pset"))
3415 static const char *const my_list[] =
3416 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3417 "footer", "format", "linestyle", "null", "numericlocale",
3418 "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3419 "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3420 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3422 COMPLETE_WITH_LIST_CS(my_list);
3424 else if (TailMatchesCS2("\\pset", MatchAny))
3426 if (TailMatchesCS1("format"))
3428 static const char *const my_list[] =
3429 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3430 "latex", "latex-longtable", "troff-ms", NULL};
3432 COMPLETE_WITH_LIST_CS(my_list);
3434 else if (TailMatchesCS1("linestyle"))
3435 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3436 else if (TailMatchesCS1("unicode_border_linestyle|"
3437 "unicode_column_linestyle|"
3438 "unicode_header_linestyle"))
3439 COMPLETE_WITH_LIST_CS2("single", "double");
3441 else if (TailMatchesCS1("\\unset"))
3443 matches = complete_from_variables(text, "", "", true);
3445 else if (TailMatchesCS1("\\set"))
3447 matches = complete_from_variables(text, "", "", false);
3449 else if (TailMatchesCS2("\\set", MatchAny))
3451 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3452 "SINGLELINE|SINGLESTEP"))
3453 COMPLETE_WITH_LIST_CS2("on", "off");
3454 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3455 COMPLETE_WITH_LIST_CS4("lower", "upper",
3456 "preserve-lower", "preserve-upper");
3457 else if (TailMatchesCS1("ECHO"))
3458 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3459 else if (TailMatchesCS1("ECHO_HIDDEN"))
3460 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3461 else if (TailMatchesCS1("HISTCONTROL"))
3462 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3463 "ignoreboth", "none");
3464 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3465 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3466 else if (TailMatchesCS1("SHOW_CONTEXT"))
3467 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3468 else if (TailMatchesCS1("VERBOSITY"))
3469 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3471 else if (TailMatchesCS1("\\sf*"))
3472 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3473 else if (TailMatchesCS1("\\sv*"))
3474 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3475 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3476 "\\ir|\\include_relative|\\o|\\out|"
3477 "\\s|\\w|\\write|\\lo_import"))
3479 completion_charp = "\\";
3480 matches = completion_matches(text, complete_from_files);
3484 * Finally, we look through the list of "things", such as TABLE, INDEX and
3485 * check if that was the previous word. If so, execute the query to get a
3492 for (i = 0; words_after_create[i].name; i++)
3494 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3496 if (words_after_create[i].query)
3497 COMPLETE_WITH_QUERY(words_after_create[i].query);
3498 else if (words_after_create[i].squery)
3499 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3507 * If we still don't have anything to match we have to fabricate some sort
3508 * of default list. If we were to just return NULL, readline automatically
3509 * attempts filename completion, and that's usually no good.
3511 if (matches == NULL)
3513 COMPLETE_WITH_CONST("");
3514 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3515 rl_completion_append_character = '\0';
3520 free(previous_words);
3523 /* Return our Grand List O' Matches */
3529 * GENERATOR FUNCTIONS
3531 * These functions do all the actual work of completing the input. They get
3532 * passed the text so far and the count how many times they have been called
3533 * so far with the same text.
3534 * If you read the above carefully, you'll see that these don't get called
3535 * directly but through the readline interface.
3536 * The return value is expected to be the full completion of the text, going
3537 * through a list each time, or NULL if there are no more matches. The string
3538 * will be free()'d by readline, so you must run it through strdup() or
3539 * something of that sort.
3543 * Common routine for create_command_generator and drop_command_generator.
3544 * Entries that have 'excluded' flags are not returned.
3547 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3549 static int list_index,
3553 /* If this is the first time for this completion, init some values */
3557 string_length = strlen(text);
3560 /* find something that matches */
3561 while ((name = words_after_create[list_index++].name))
3563 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3564 !(words_after_create[list_index - 1].flags & excluded))
3565 return pg_strdup_keyword_case(name, text);
3567 /* if nothing matches, return NULL */
3572 * This one gives you one from a list of things you can put after CREATE
3576 create_command_generator(const char *text, int state)
3578 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3582 * This function gives you a list of things you can put after a DROP command.
3585 drop_command_generator(const char *text, int state)
3587 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3591 * This function gives you a list of things you can put after an ALTER command.
3594 alter_command_generator(const char *text, int state)
3596 return create_or_drop_command_generator(text, state, THING_NO_ALTER);
3599 /* The following two functions are wrappers for _complete_from_query */
3602 complete_from_query(const char *text, int state)
3604 return _complete_from_query(0, text, state);
3608 complete_from_schema_query(const char *text, int state)
3610 return _complete_from_query(1, text, state);
3615 * This creates a list of matching things, according to a query pointed to
3616 * by completion_charp.
3617 * The query can be one of two kinds:
3619 * 1. A simple query which must contain a %d and a %s, which will be replaced
3620 * by the string length of the text and the text itself. The query may also
3621 * have up to four more %s in it; the first two such will be replaced by the
3622 * value of completion_info_charp, the next two by the value of
3623 * completion_info_charp2.
3625 * 2. A schema query used for completion of both schema and relation names.
3626 * These are more complex and must contain in the following order:
3627 * %d %s %d %s %d %s %s %d %s
3628 * where %d is the string length of the text and %s the text itself.
3630 * It is assumed that strings should be escaped to become SQL literals
3631 * (that is, what is in the query is actually ... '%s' ...)
3633 * See top of file for examples of both kinds of query.
3636 _complete_from_query(int is_schema_query, const char *text, int state)
3638 static int list_index,
3640 static PGresult *result = NULL;
3643 * If this is the first time for this completion, we fetch a list of our
3644 * "things" from the backend.
3648 PQExpBufferData query_buffer;
3651 char *e_info_charp2;
3652 const char *pstr = text;
3653 int char_length = 0;
3656 byte_length = strlen(text);
3659 * Count length as number of characters (not bytes), for passing to
3665 pstr += PQmblen(pstr, pset.encoding);
3668 /* Free any prior result */
3672 /* Set up suitably-escaped copies of textual inputs */
3673 e_text = escape_string(text);
3675 if (completion_info_charp)
3676 e_info_charp = escape_string(completion_info_charp);
3678 e_info_charp = NULL;
3680 if (completion_info_charp2)
3681 e_info_charp2 = escape_string(completion_info_charp2);
3683 e_info_charp2 = NULL;
3685 initPQExpBuffer(&query_buffer);
3687 if (is_schema_query)
3689 /* completion_squery gives us the pieces to assemble */
3690 const char *qualresult = completion_squery->qualresult;
3692 if (qualresult == NULL)
3693 qualresult = completion_squery->result;
3695 /* Get unqualified names matching the input-so-far */
3696 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3697 completion_squery->result,
3698 completion_squery->catname);
3699 if (completion_squery->selcondition)
3700 appendPQExpBuffer(&query_buffer, "%s AND ",
3701 completion_squery->selcondition);
3702 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3703 completion_squery->result,
3704 char_length, e_text);
3705 appendPQExpBuffer(&query_buffer, " AND %s",
3706 completion_squery->viscondition);
3709 * When fetching relation names, suppress system catalogs unless
3710 * the input-so-far begins with "pg_". This is a compromise
3711 * between not offering system catalogs for completion at all, and
3712 * having them swamp the result when the input is just "p".
3714 if (strcmp(completion_squery->catname,
3715 "pg_catalog.pg_class c") == 0 &&
3716 strncmp(text, "pg_", 3) !=0)
3718 appendPQExpBufferStr(&query_buffer,
3719 " AND c.relnamespace <> (SELECT oid FROM"
3720 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3724 * Add in matching schema names, but only if there is more than
3725 * one potential match among schema names.
3727 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3728 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3729 "FROM pg_catalog.pg_namespace n "
3730 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3731 char_length, e_text);
3732 appendPQExpBuffer(&query_buffer,
3733 " AND (SELECT pg_catalog.count(*)"
3734 " FROM pg_catalog.pg_namespace"
3735 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3736 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3737 char_length, e_text);
3740 * Add in matching qualified names, but only if there is exactly
3741 * one schema matching the input-so-far.
3743 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3744 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3745 "FROM %s, pg_catalog.pg_namespace n "
3746 "WHERE %s = n.oid AND ",
3748 completion_squery->catname,
3749 completion_squery->namespace);
3750 if (completion_squery->selcondition)
3751 appendPQExpBuffer(&query_buffer, "%s AND ",
3752 completion_squery->selcondition);
3753 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3755 char_length, e_text);
3758 * This condition exploits the single-matching-schema rule to
3759 * speed up the query
3761 appendPQExpBuffer(&query_buffer,
3762 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3763 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3764 char_length, e_text);
3765 appendPQExpBuffer(&query_buffer,
3766 " AND (SELECT pg_catalog.count(*)"
3767 " FROM pg_catalog.pg_namespace"
3768 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3769 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3770 char_length, e_text);
3772 /* If an addon query was provided, use it */
3773 if (completion_charp)
3774 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3778 /* completion_charp is an sprintf-style format string */
3779 appendPQExpBuffer(&query_buffer, completion_charp,
3780 char_length, e_text,
3781 e_info_charp, e_info_charp,
3782 e_info_charp2, e_info_charp2);
3785 /* Limit the number of records in the result */
3786 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3787 completion_max_records);
3789 result = exec_query(query_buffer.data);
3791 termPQExpBuffer(&query_buffer);
3796 free(e_info_charp2);
3799 /* Find something that matches */
3800 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3804 while (list_index < PQntuples(result) &&
3805 (item = PQgetvalue(result, list_index++, 0)))
3806 if (pg_strncasecmp(text, item, byte_length) == 0)
3807 return pg_strdup(item);
3810 /* If nothing matches, free the db structure and return null */
3818 * This function returns in order one of a fixed, NULL pointer terminated list
3819 * of strings (if matching). This can be used if there are only a fixed number
3820 * SQL words that can appear at certain spot.
3823 complete_from_list(const char *text, int state)
3825 static int string_length,
3828 static bool casesensitive;
3831 /* need to have a list */
3832 Assert(completion_charpp != NULL);
3834 /* Initialization */
3838 string_length = strlen(text);
3839 casesensitive = completion_case_sensitive;
3843 while ((item = completion_charpp[list_index++]))
3845 /* First pass is case sensitive */
3846 if (casesensitive && strncmp(text, item, string_length) == 0)
3849 return pg_strdup(item);
3852 /* Second pass is case insensitive, don't bother counting matches */
3853 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3855 if (completion_case_sensitive)
3856 return pg_strdup(item);
3860 * If case insensitive matching was requested initially,
3861 * adjust the case according to setting.
3863 return pg_strdup_keyword_case(item, text);
3868 * No matches found. If we're not case insensitive already, lets switch to
3869 * being case insensitive and try again
3871 if (casesensitive && matches == 0)
3873 casesensitive = false;
3876 return complete_from_list(text, state);
3879 /* If no more matches, return null. */
3885 * This function returns one fixed string the first time even if it doesn't
3886 * match what's there, and nothing the second time. This should be used if
3887 * there is only one possibility that can appear at a certain spot, so
3888 * misspellings will be overwritten. The string to be passed must be in
3892 complete_from_const(const char *text, int state)
3894 Assert(completion_charp != NULL);
3897 if (completion_case_sensitive)
3898 return pg_strdup(completion_charp);
3902 * If case insensitive matching was requested initially, adjust
3903 * the case according to setting.
3905 return pg_strdup_keyword_case(completion_charp, text);
3913 * This function appends the variable name with prefix and suffix to
3914 * the variable names array.
3917 append_variable_names(char ***varnames, int *nvars,
3918 int *maxvars, const char *varname,
3919 const char *prefix, const char *suffix)
3921 if (*nvars >= *maxvars)
3924 *varnames = (char **) pg_realloc(*varnames,
3925 ((*maxvars) + 1) * sizeof(char *));
3928 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3933 * This function supports completion with the name of a psql variable.
3934 * The variable names can be prefixed and suffixed with additional text
3935 * to support quoting usages. If need_value is true, only variables
3936 * that are currently set are included; otherwise, special variables
3937 * (those that have hooks) are included even if currently unset.
3940 complete_from_variables(const char *text, const char *prefix, const char *suffix,
3948 struct _variable *ptr;
3950 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
3952 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3954 if (need_value && !(ptr->value))
3956 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3960 varnames[nvars] = NULL;
3961 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
3963 for (i = 0; i < nvars; i++)
3972 * This function wraps rl_filename_completion_function() to strip quotes from
3973 * the input before searching for matches and to quote any matches for which
3974 * the consuming command will require it.
3977 complete_from_files(const char *text, int state)
3979 static const char *unquoted_text;
3980 char *unquoted_match;
3985 /* Initialization: stash the unquoted input. */
3986 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
3987 false, true, pset.encoding);
3988 /* expect a NULL return for the empty string only */
3991 Assert(*text == '\0');
3992 unquoted_text = text;
3996 unquoted_match = filename_completion_function(unquoted_text, state);
4000 * Caller sets completion_charp to a zero- or one-character string
4001 * containing the escape character. This is necessary since \copy has
4002 * no escape character, but every other backslash command recognizes
4003 * "\" as an escape character. Since we have only two callers, don't
4004 * bother providing a macro to simplify this.
4006 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
4007 '\'', *completion_charp, pset.encoding);
4009 free(unquoted_match);
4011 ret = unquoted_match;
4018 /* HELPER FUNCTIONS */
4022 * Make a pg_strdup copy of s and convert the case according to
4023 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
4026 pg_strdup_keyword_case(const char *s, const char *ref)
4030 unsigned char first = ref[0];
4034 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
4035 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
4036 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
4037 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
4039 for (p = ret; *p; p++)
4040 *p = pg_tolower((unsigned char) *p);
4044 for (p = ret; *p; p++)
4045 *p = pg_toupper((unsigned char) *p);
4053 * escape_string - Escape argument for use as string literal.
4055 * The returned value has to be freed.
4058 escape_string(const char *text)
4063 text_length = strlen(text);
4065 result = pg_malloc(text_length * 2 + 1);
4066 PQescapeStringConn(pset.db, result, text, text_length, NULL);
4073 * Execute a query and report any errors. This should be the preferred way of
4074 * talking to the database in this file.
4077 exec_query(const char *query)
4081 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
4084 result = PQexec(pset.db, query);
4086 if (PQresultStatus(result) != PGRES_TUPLES_OK)
4089 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
4090 PQerrorMessage(pset.db), query);
4101 * Parse all the word(s) before point.
4103 * Returns a malloc'd array of character pointers that point into the malloc'd
4104 * data array returned to *buffer; caller must free() both of these when done.
4105 * *nwords receives the number of words found, ie, the valid length of the
4108 * Words are returned right to left, that is, previous_words[0] gets the last
4109 * word before point, previous_words[1] the next-to-last, etc.
4112 get_previous_words(int point, char **buffer, int *nwords)
4114 char **previous_words;
4117 int words_found = 0;
4121 * If we have anything in tab_completion_query_buf, paste it together with
4122 * rl_line_buffer to construct the full query. Otherwise we can just use
4123 * rl_line_buffer as the input string.
4125 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
4127 i = tab_completion_query_buf->len;
4128 buf = pg_malloc(point + i + 2);
4129 memcpy(buf, tab_completion_query_buf->data, i);
4131 memcpy(buf + i, rl_line_buffer, point);
4134 /* Readjust point to reference appropriate offset in buf */
4138 buf = rl_line_buffer;
4141 * Allocate an array of string pointers and a buffer to hold the strings
4142 * themselves. The worst case is that the line contains only
4143 * non-whitespace WORD_BREAKS characters, making each one a separate word.
4144 * This is usually much more space than we need, but it's cheaper than
4145 * doing a separate malloc() for each word.
4147 previous_words = (char **) pg_malloc(point * sizeof(char *));
4148 *buffer = outptr = (char *) pg_malloc(point * 2);
4151 * First we look for a non-word char before the current point. (This is
4152 * probably useless, if readline is on the same page as we are about what
4153 * is a word, but if so it's cheap.)
4155 for (i = point - 1; i >= 0; i--)
4157 if (strchr(WORD_BREAKS, buf[i]))
4163 * Now parse words, working backwards, until we hit start of line. The
4164 * backwards scan has some interesting but intentional properties
4165 * concerning parenthesis handling.
4171 bool inquotes = false;
4172 int parentheses = 0;
4174 /* now find the first non-space which then constitutes the end */
4176 for (i = point; i >= 0; i--)
4178 if (!isspace((unsigned char) buf[i]))
4184 /* if no end found, we're done */
4189 * Otherwise we now look for the start. The start is either the last
4190 * character before any word-break character going backwards from the
4191 * end, or it's simply character 0. We also handle open quotes and
4194 for (start = end; start > 0; start--)
4196 if (buf[start] == '"')
4197 inquotes = !inquotes;
4200 if (buf[start] == ')')
4202 else if (buf[start] == '(')
4204 if (--parentheses <= 0)
4207 else if (parentheses == 0 &&
4208 strchr(WORD_BREAKS, buf[start - 1]))
4213 /* Return the word located at start to end inclusive */
4214 previous_words[words_found++] = outptr;
4215 i = end - start + 1;
4216 memcpy(outptr, &buf[start], i);
4220 /* Continue searching */
4224 /* Release parsing input workspace, if we made one above */
4225 if (buf != rl_line_buffer)
4228 *nwords = words_found;
4229 return previous_words;
4233 * Look up the type for the GUC variable with the passed name.
4235 * Returns NULL if the variable is unknown. Otherwise the returned string,
4236 * containing the type, has to be freed.
4239 get_guctype(const char *varname)
4241 PQExpBufferData query_buffer;
4244 char *guctype = NULL;
4246 e_varname = escape_string(varname);
4248 initPQExpBuffer(&query_buffer);
4249 appendPQExpBuffer(&query_buffer,
4250 "SELECT vartype FROM pg_catalog.pg_settings "
4251 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
4254 result = exec_query(query_buffer.data);
4255 termPQExpBuffer(&query_buffer);
4258 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
4259 guctype = pg_strdup(PQgetvalue(result, 0, 0));
4269 * Surround a string with single quotes. This works for both SQL and
4270 * psql internal. Currently disabled because it is reported not to
4271 * cooperate with certain versions of readline.
4274 quote_file_name(char *text, int match_type, char *quote_pointer)
4279 (void) quote_pointer; /* not used */
4281 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
4282 s = pg_malloc(length);
4284 strcpy(s + 1, text);
4285 if (match_type == SINGLE_MATCH)
4286 s[length - 2] = '\'';
4287 s[length - 1] = '\0';
4292 dequote_file_name(char *text, char quote_char)
4298 return pg_strdup(text);
4300 length = strlen(text);
4301 s = pg_malloc(length - 2 + 1);
4302 strlcpy(s, text +1, length - 2 + 1);
4306 #endif /* NOT_USED */
4308 #endif /* USE_READLINE */