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_SHOW (THING_NO_CREATE | THING_NO_DROP)
987 static const pgsql_thing_t words_after_create[] = {
988 {"ACCESS METHOD", NULL, NULL},
989 {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
990 {"CAST", NULL, NULL}, /* Casts have complex structures for names, so
992 {"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'"},
995 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
996 * to be used only by pg_dump.
998 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
999 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
1000 {"DATABASE", Query_for_list_of_databases},
1001 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
1002 {"DOMAIN", NULL, &Query_for_list_of_domains},
1003 {"EVENT TRIGGER", NULL, NULL},
1004 {"EXTENSION", Query_for_list_of_extensions},
1005 {"FOREIGN DATA WRAPPER", NULL, NULL},
1006 {"FOREIGN TABLE", NULL, NULL},
1007 {"FUNCTION", NULL, &Query_for_list_of_functions},
1008 {"GROUP", Query_for_list_of_roles},
1009 {"LANGUAGE", Query_for_list_of_languages},
1010 {"INDEX", NULL, &Query_for_list_of_indexes},
1011 {"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
1012 {"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a
1014 {"OWNED", NULL, NULL, THING_NO_CREATE}, /* for DROP OWNED BY ... */
1015 {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
1016 {"POLICY", NULL, NULL},
1017 {"PUBLICATION", Query_for_list_of_publications},
1018 {"ROLE", Query_for_list_of_roles},
1019 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
1020 {"SCHEMA", Query_for_list_of_schemas},
1021 {"SEQUENCE", NULL, &Query_for_list_of_sequences},
1022 {"SERVER", Query_for_list_of_servers},
1023 {"SUBSCRIPTION", Query_for_list_of_subscriptions},
1024 {"TABLE", NULL, &Query_for_list_of_tables},
1025 {"TABLESPACE", Query_for_list_of_tablespaces},
1026 {"TEMP", NULL, NULL, THING_NO_DROP}, /* for CREATE TEMP TABLE ... */
1027 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
1028 {"TEXT SEARCH", NULL, NULL},
1029 {"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"},
1030 {"TYPE", NULL, &Query_for_list_of_datatypes},
1031 {"UNIQUE", NULL, NULL, THING_NO_DROP}, /* for CREATE UNIQUE INDEX ... */
1032 {"UNLOGGED", NULL, NULL, THING_NO_DROP}, /* for CREATE UNLOGGED TABLE
1034 {"USER", Query_for_list_of_roles},
1035 {"USER MAPPING FOR", NULL, NULL},
1036 {"VIEW", NULL, &Query_for_list_of_views},
1037 {NULL} /* end of list */
1041 /* Forward declaration of functions */
1042 static char **psql_completion(const char *text, int start, int end);
1043 static char *create_command_generator(const char *text, int state);
1044 static char *drop_command_generator(const char *text, int state);
1045 static char *complete_from_query(const char *text, int state);
1046 static char *complete_from_schema_query(const char *text, int state);
1047 static char *_complete_from_query(int is_schema_query,
1048 const char *text, int state);
1049 static char *complete_from_list(const char *text, int state);
1050 static char *complete_from_const(const char *text, int state);
1051 static void append_variable_names(char ***varnames, int *nvars,
1052 int *maxvars, const char *varname,
1053 const char *prefix, const char *suffix);
1054 static char **complete_from_variables(const char *text,
1055 const char *prefix, const char *suffix, bool need_value);
1056 static char *complete_from_files(const char *text, int state);
1058 static char *pg_strdup_keyword_case(const char *s, const char *ref);
1059 static char *escape_string(const char *text);
1060 static PGresult *exec_query(const char *query);
1062 static char **get_previous_words(int point, char **buffer, int *nwords);
1064 static char *get_guctype(const char *varname);
1067 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
1068 static char *dequote_file_name(char *text, char quote_char);
1073 * Initialize the readline library for our purposes.
1076 initialize_readline(void)
1078 rl_readline_name = (char *) pset.progname;
1079 rl_attempted_completion_function = psql_completion;
1081 rl_basic_word_break_characters = WORD_BREAKS;
1083 completion_max_records = 1000;
1086 * There is a variable rl_completion_query_items for this but apparently
1087 * it's not defined everywhere.
1092 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1093 * using case-insensitive or case-sensitive comparisons.
1095 * If pattern is NULL, it's a wild card that matches any word.
1096 * If pattern begins with '!', the result is negated, ie we check that 'word'
1097 * does *not* match any alternative appearing in the rest of 'pattern'.
1098 * Any alternative can end with '*' which is a wild card, i.e., it means
1099 * match any word that matches the characters so far. (We do not currently
1100 * support '*' elsewhere than the end of an alternative.)
1102 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1103 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1104 * just be written directly in patterns.)
1106 #define MatchAny NULL
1107 #define MatchAnyExcept(pattern) ("!" pattern)
1110 word_matches_internal(const char *pattern,
1112 bool case_sensitive)
1117 /* NULL pattern matches anything. */
1118 if (pattern == NULL)
1121 /* Handle negated patterns from the MatchAnyExcept macro. */
1122 if (*pattern == '!')
1123 return !word_matches_internal(pattern + 1, word, case_sensitive);
1125 /* Else consider each alternative in the pattern. */
1126 wordlen = strlen(word);
1131 /* Find end of current alternative. */
1133 while (*c != '\0' && *c != '|')
1135 /* Was there a wild card? (Assumes first alternative is not empty) */
1138 /* Yes, wildcard match? */
1139 patternlen = c - pattern - 1;
1140 if (wordlen >= patternlen &&
1142 strncmp(word, pattern, patternlen) == 0 :
1143 pg_strncasecmp(word, pattern, patternlen) == 0))
1148 /* No, plain match? */
1149 patternlen = c - pattern;
1150 if (wordlen == patternlen &&
1152 strncmp(word, pattern, wordlen) == 0 :
1153 pg_strncasecmp(word, pattern, wordlen) == 0))
1156 /* Out of alternatives? */
1159 /* Nope, try next alternative. */
1167 * There are enough matching calls below that it seems worth having these two
1168 * interface routines rather than including a third parameter in every call.
1170 * word_matches --- match case-insensitively.
1173 word_matches(const char *pattern, const char *word)
1175 return word_matches_internal(pattern, word, false);
1179 * word_matches_cs --- match case-sensitively.
1182 word_matches_cs(const char *pattern, const char *word)
1184 return word_matches_internal(pattern, word, true);
1188 * Check if the final character of 's' is 'c'.
1191 ends_with(const char *s, char c)
1193 size_t length = strlen(s);
1195 return (length > 0 && s[length - 1] == c);
1199 * The completion function.
1201 * According to readline spec this gets passed the text entered so far and its
1202 * start and end positions in the readline buffer. The return value is some
1203 * partially obscure list format that can be generated by readline's
1204 * completion_matches() function, so we don't have to worry about it.
1207 psql_completion(const char *text, int start, int end)
1209 /* This is the variable we'll return. */
1210 char **matches = NULL;
1212 /* Workspace for parsed words. */
1215 /* This array will contain pointers to parsed words. */
1216 char **previous_words;
1218 /* The number of words found on the input line. */
1219 int previous_words_count;
1222 * For compactness, we use these macros to reference previous_words[].
1223 * Caution: do not access a previous_words[] entry without having checked
1224 * previous_words_count to be sure it's valid. In most cases below, that
1225 * check is implicit in a TailMatches() or similar macro, but in some
1226 * places we have to check it explicitly.
1228 #define prev_wd (previous_words[0])
1229 #define prev2_wd (previous_words[1])
1230 #define prev3_wd (previous_words[2])
1231 #define prev4_wd (previous_words[3])
1232 #define prev5_wd (previous_words[4])
1233 #define prev6_wd (previous_words[5])
1234 #define prev7_wd (previous_words[6])
1235 #define prev8_wd (previous_words[7])
1236 #define prev9_wd (previous_words[8])
1238 /* Macros for matching the last N words before point, case-insensitively. */
1239 #define TailMatches1(p1) \
1240 (previous_words_count >= 1 && \
1241 word_matches(p1, prev_wd))
1243 #define TailMatches2(p2, p1) \
1244 (previous_words_count >= 2 && \
1245 word_matches(p1, prev_wd) && \
1246 word_matches(p2, prev2_wd))
1248 #define TailMatches3(p3, p2, p1) \
1249 (previous_words_count >= 3 && \
1250 word_matches(p1, prev_wd) && \
1251 word_matches(p2, prev2_wd) && \
1252 word_matches(p3, prev3_wd))
1254 #define TailMatches4(p4, p3, p2, p1) \
1255 (previous_words_count >= 4 && \
1256 word_matches(p1, prev_wd) && \
1257 word_matches(p2, prev2_wd) && \
1258 word_matches(p3, prev3_wd) && \
1259 word_matches(p4, prev4_wd))
1261 #define TailMatches5(p5, p4, p3, p2, p1) \
1262 (previous_words_count >= 5 && \
1263 word_matches(p1, prev_wd) && \
1264 word_matches(p2, prev2_wd) && \
1265 word_matches(p3, prev3_wd) && \
1266 word_matches(p4, prev4_wd) && \
1267 word_matches(p5, prev5_wd))
1269 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1270 (previous_words_count >= 6 && \
1271 word_matches(p1, prev_wd) && \
1272 word_matches(p2, prev2_wd) && \
1273 word_matches(p3, prev3_wd) && \
1274 word_matches(p4, prev4_wd) && \
1275 word_matches(p5, prev5_wd) && \
1276 word_matches(p6, prev6_wd))
1278 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1279 (previous_words_count >= 7 && \
1280 word_matches(p1, prev_wd) && \
1281 word_matches(p2, prev2_wd) && \
1282 word_matches(p3, prev3_wd) && \
1283 word_matches(p4, prev4_wd) && \
1284 word_matches(p5, prev5_wd) && \
1285 word_matches(p6, prev6_wd) && \
1286 word_matches(p7, prev7_wd))
1288 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1289 (previous_words_count >= 8 && \
1290 word_matches(p1, prev_wd) && \
1291 word_matches(p2, prev2_wd) && \
1292 word_matches(p3, prev3_wd) && \
1293 word_matches(p4, prev4_wd) && \
1294 word_matches(p5, prev5_wd) && \
1295 word_matches(p6, prev6_wd) && \
1296 word_matches(p7, prev7_wd) && \
1297 word_matches(p8, prev8_wd))
1299 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1300 (previous_words_count >= 9 && \
1301 word_matches(p1, prev_wd) && \
1302 word_matches(p2, prev2_wd) && \
1303 word_matches(p3, prev3_wd) && \
1304 word_matches(p4, prev4_wd) && \
1305 word_matches(p5, prev5_wd) && \
1306 word_matches(p6, prev6_wd) && \
1307 word_matches(p7, prev7_wd) && \
1308 word_matches(p8, prev8_wd) && \
1309 word_matches(p9, prev9_wd))
1311 /* Macros for matching the last N words before point, case-sensitively. */
1312 #define TailMatchesCS1(p1) \
1313 (previous_words_count >= 1 && \
1314 word_matches_cs(p1, prev_wd))
1315 #define TailMatchesCS2(p2, p1) \
1316 (previous_words_count >= 2 && \
1317 word_matches_cs(p1, prev_wd) && \
1318 word_matches_cs(p2, prev2_wd))
1321 * Macros for matching N words beginning at the start of the line,
1322 * case-insensitively.
1324 #define Matches1(p1) \
1325 (previous_words_count == 1 && \
1327 #define Matches2(p1, p2) \
1328 (previous_words_count == 2 && \
1329 TailMatches2(p1, p2))
1330 #define Matches3(p1, p2, p3) \
1331 (previous_words_count == 3 && \
1332 TailMatches3(p1, p2, p3))
1333 #define Matches4(p1, p2, p3, p4) \
1334 (previous_words_count == 4 && \
1335 TailMatches4(p1, p2, p3, p4))
1336 #define Matches5(p1, p2, p3, p4, p5) \
1337 (previous_words_count == 5 && \
1338 TailMatches5(p1, p2, p3, p4, p5))
1339 #define Matches6(p1, p2, p3, p4, p5, p6) \
1340 (previous_words_count == 6 && \
1341 TailMatches6(p1, p2, p3, p4, p5, p6))
1342 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1343 (previous_words_count == 7 && \
1344 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1345 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1346 (previous_words_count == 8 && \
1347 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1348 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1349 (previous_words_count == 9 && \
1350 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1353 * Macros for matching N words at the start of the line, regardless of
1354 * what is after them, case-insensitively.
1356 #define HeadMatches1(p1) \
1357 (previous_words_count >= 1 && \
1358 word_matches(p1, previous_words[previous_words_count - 1]))
1360 #define HeadMatches2(p1, p2) \
1361 (previous_words_count >= 2 && \
1362 word_matches(p1, previous_words[previous_words_count - 1]) && \
1363 word_matches(p2, previous_words[previous_words_count - 2]))
1365 #define HeadMatches3(p1, p2, p3) \
1366 (previous_words_count >= 3 && \
1367 word_matches(p1, previous_words[previous_words_count - 1]) && \
1368 word_matches(p2, previous_words[previous_words_count - 2]) && \
1369 word_matches(p3, previous_words[previous_words_count - 3]))
1371 /* Known command-starting keywords. */
1372 static const char *const sql_commands[] = {
1373 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
1374 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1375 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1376 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1377 "MOVE", "NOTIFY", "PREPARE",
1378 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1379 "RESET", "REVOKE", "ROLLBACK",
1380 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1381 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1385 /* psql's backslash commands. */
1386 static const char *const backslash_commands[] = {
1387 "\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1388 "\\copyright", "\\crosstabview",
1389 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1390 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1391 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1392 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
1393 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1394 "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
1395 "\\f", "\\g", "\\gexec", "\\gset", "\\gx", "\\h", "\\help", "\\H",
1396 "\\i", "\\ir", "\\l", "\\lo_import", "\\lo_export", "\\lo_list",
1397 "\\lo_unlink", "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q",
1398 "\\qecho", "\\r", "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t",
1399 "\\T", "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!",
1403 (void) end; /* "end" is not used */
1405 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1406 rl_completion_append_character = ' ';
1409 /* Clear a few things. */
1410 completion_charp = NULL;
1411 completion_charpp = NULL;
1412 completion_info_charp = NULL;
1413 completion_info_charp2 = NULL;
1416 * Scan the input line to extract the words before our current position.
1417 * According to those we'll make some smart decisions on what the user is
1418 * probably intending to type.
1420 previous_words = get_previous_words(start,
1422 &previous_words_count);
1424 /* If current word is a backslash command, offer completions for that */
1425 if (text[0] == '\\')
1426 COMPLETE_WITH_LIST_CS(backslash_commands);
1428 /* If current word is a variable interpolation, handle that case */
1429 else if (text[0] == ':' && text[1] != ':')
1431 if (text[1] == '\'')
1432 matches = complete_from_variables(text, ":'", "'", true);
1433 else if (text[1] == '"')
1434 matches = complete_from_variables(text, ":\"", "\"", true);
1436 matches = complete_from_variables(text, ":", "", true);
1439 /* If no previous word, suggest one of the basic sql commands */
1440 else if (previous_words_count == 0)
1441 COMPLETE_WITH_LIST(sql_commands);
1444 /* complete with something you can create */
1445 else if (TailMatches1("CREATE"))
1446 matches = completion_matches(text, create_command_generator);
1448 /* DROP, but not DROP embedded in other commands */
1449 /* complete with something you can drop */
1450 else if (Matches1("DROP"))
1451 matches = completion_matches(text, drop_command_generator);
1456 else if (Matches2("ALTER", "TABLE"))
1457 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1458 "UNION SELECT 'ALL IN TABLESPACE'");
1460 /* ALTER something */
1461 else if (Matches1("ALTER"))
1463 static const char *const list_ALTER[] =
1464 {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
1465 "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
1466 "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR",
1467 "POLICY", "PUBLICATION", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE",
1468 "SUBSCRIPTION", "SYSTEM", "TABLE", "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
1469 "USER", "USER MAPPING FOR", "VIEW", NULL};
1471 COMPLETE_WITH_LIST(list_ALTER);
1473 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1474 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1475 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1476 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1477 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1478 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1479 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1480 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1481 COMPLETE_WITH_CONST("SET TABLESPACE");
1482 /* ALTER AGGREGATE,FUNCTION <name> */
1483 else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1484 COMPLETE_WITH_CONST("(");
1485 /* ALTER AGGREGATE,FUNCTION <name> (...) */
1486 else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1488 if (ends_with(prev_wd, ')'))
1489 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1491 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1493 /* ALTER PUBLICATION <name> ...*/
1494 else if (Matches3("ALTER","PUBLICATION",MatchAny))
1496 COMPLETE_WITH_LIST6("WITH", "ADD TABLE", "SET TABLE", "DROP TABLE",
1497 "OWNER TO", "RENAME TO");
1499 /* ALTER PUBLICATION <name> .. WITH ( ... */
1500 else if (HeadMatches3("ALTER", "PUBLICATION",MatchAny) && TailMatches2("WITH", "("))
1502 COMPLETE_WITH_LIST6("PUBLISH INSERT", "NOPUBLISH INSERT", "PUBLISH UPDATE",
1503 "NOPUBLISH UPDATE", "PUBLISH DELETE", "NOPUBLISH DELETE");
1505 /* ALTER SUBSCRIPTION <name> ... */
1506 else if (Matches3("ALTER","SUBSCRIPTION",MatchAny))
1508 COMPLETE_WITH_LIST7("WITH", "CONNECTION", "SET PUBLICATION", "ENABLE",
1509 "DISABLE", "OWNER TO", "RENAME TO");
1511 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("WITH", "("))
1513 COMPLETE_WITH_CONST("SLOT NAME");
1515 /* ALTER SCHEMA <name> */
1516 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1517 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1519 /* ALTER COLLATION <name> */
1520 else if (Matches3("ALTER", "COLLATION", MatchAny))
1521 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1523 /* ALTER CONVERSION <name> */
1524 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1525 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1527 /* ALTER DATABASE <name> */
1528 else if (Matches3("ALTER", "DATABASE", MatchAny))
1529 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1530 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1531 "CONNECTION LIMIT");
1533 /* ALTER EVENT TRIGGER */
1534 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1535 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1537 /* ALTER EVENT TRIGGER <name> */
1538 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1539 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1541 /* ALTER EVENT TRIGGER <name> ENABLE */
1542 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1543 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1545 /* ALTER EXTENSION <name> */
1546 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1547 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1549 /* ALTER EXTENSION <name> UPDATE */
1550 else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
1552 completion_info_charp = prev2_wd;
1553 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
1556 /* ALTER EXTENSION <name> UPDATE TO */
1557 else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
1559 completion_info_charp = prev3_wd;
1560 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
1564 else if (Matches2("ALTER", "FOREIGN"))
1565 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1567 /* ALTER FOREIGN DATA WRAPPER <name> */
1568 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1569 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1571 /* ALTER FOREIGN TABLE <name> */
1572 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1574 static const char *const list_ALTER_FOREIGN_TABLE[] =
1575 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1576 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1577 "VALIDATE CONSTRAINT", NULL};
1579 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1583 else if (Matches2("ALTER", "INDEX"))
1584 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1585 "UNION SELECT 'ALL IN TABLESPACE'");
1586 /* ALTER INDEX <name> */
1587 else if (Matches3("ALTER", "INDEX", MatchAny))
1588 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1589 /* ALTER INDEX <name> SET */
1590 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1591 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1592 /* ALTER INDEX <name> RESET */
1593 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1594 COMPLETE_WITH_CONST("(");
1595 /* ALTER INDEX <foo> SET|RESET ( */
1596 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1597 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1598 "gin_pending_list_limit");
1599 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1600 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1601 "gin_pending_list_limit =");
1603 /* ALTER LANGUAGE <name> */
1604 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1605 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1607 /* ALTER LARGE OBJECT <oid> */
1608 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1609 COMPLETE_WITH_CONST("OWNER TO");
1611 /* ALTER MATERIALIZED VIEW */
1612 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1613 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1614 "UNION SELECT 'ALL IN TABLESPACE'");
1616 /* ALTER USER,ROLE <name> */
1617 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1618 !TailMatches2("USER", "MAPPING"))
1620 static const char *const list_ALTERUSER[] =
1621 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1622 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1623 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1624 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1625 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1626 "VALID UNTIL", "WITH", NULL};
1628 COMPLETE_WITH_LIST(list_ALTERUSER);
1631 /* ALTER USER,ROLE <name> WITH */
1632 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1634 /* Similar to the above, but don't complete "WITH" again. */
1635 static const char *const list_ALTERUSER_WITH[] =
1636 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1637 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1638 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1639 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1640 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1641 "VALID UNTIL", NULL};
1643 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1646 /* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
1647 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
1648 COMPLETE_WITH_CONST("PASSWORD");
1649 /* ALTER DEFAULT PRIVILEGES */
1650 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1651 COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
1652 /* ALTER DEFAULT PRIVILEGES FOR */
1653 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1654 COMPLETE_WITH_CONST("ROLE");
1655 /* ALTER DEFAULT PRIVILEGES IN */
1656 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1657 COMPLETE_WITH_CONST("SCHEMA");
1658 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1659 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1661 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
1662 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1663 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1665 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
1666 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1667 else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1669 COMPLETE_WITH_CONST("ROLE");
1670 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
1671 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1672 else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1673 MatchAny, "IN", "SCHEMA", MatchAny) ||
1674 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1675 MatchAny, "FOR", "ROLE|USER", MatchAny))
1676 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1677 /* ALTER DOMAIN <name> */
1678 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1679 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1680 "VALIDATE CONSTRAINT");
1681 /* ALTER DOMAIN <sth> DROP */
1682 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1683 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1684 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1685 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1687 completion_info_charp = prev3_wd;
1688 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1690 /* ALTER DOMAIN <sth> RENAME */
1691 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1692 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1693 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1694 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1695 COMPLETE_WITH_CONST("TO");
1697 /* ALTER DOMAIN <sth> SET */
1698 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1699 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1700 /* ALTER SEQUENCE <name> */
1701 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1703 static const char *const list_ALTERSEQUENCE[] =
1704 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1705 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1707 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1709 /* ALTER SEQUENCE <name> NO */
1710 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1711 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1712 /* ALTER SERVER <name> */
1713 else if (Matches3("ALTER", "SERVER", MatchAny))
1714 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1715 /* ALTER SERVER <name> VERSION <version> */
1716 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1717 COMPLETE_WITH_CONST("OPTIONS");
1718 /* ALTER SYSTEM SET, RESET, RESET ALL */
1719 else if (Matches2("ALTER", "SYSTEM"))
1720 COMPLETE_WITH_LIST2("SET", "RESET");
1721 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1722 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1723 else if (Matches4("ALTER", "SYSTEM", "SET", MatchAny))
1724 COMPLETE_WITH_CONST("TO");
1725 /* ALTER VIEW <name> */
1726 else if (Matches3("ALTER", "VIEW", MatchAny))
1727 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1729 /* ALTER MATERIALIZED VIEW <name> */
1730 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1731 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1734 /* ALTER POLICY <name> */
1735 else if (Matches2("ALTER", "POLICY"))
1736 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1737 /* ALTER POLICY <name> ON */
1738 else if (Matches3("ALTER", "POLICY", MatchAny))
1739 COMPLETE_WITH_CONST("ON");
1740 /* ALTER POLICY <name> ON <table> */
1741 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1743 completion_info_charp = prev2_wd;
1744 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1746 /* ALTER POLICY <name> ON <table> - show options */
1747 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1748 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1749 /* ALTER POLICY <name> ON <table> TO <role> */
1750 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1751 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1752 /* ALTER POLICY <name> ON <table> USING ( */
1753 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1754 COMPLETE_WITH_CONST("(");
1755 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1756 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1757 COMPLETE_WITH_CONST("(");
1759 /* ALTER RULE <name>, add ON */
1760 else if (Matches3("ALTER", "RULE", MatchAny))
1761 COMPLETE_WITH_CONST("ON");
1763 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1764 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1766 completion_info_charp = prev2_wd;
1767 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1770 /* ALTER RULE <name> ON <name> */
1771 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1772 COMPLETE_WITH_CONST("RENAME TO");
1774 /* ALTER TRIGGER <name>, add ON */
1775 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1776 COMPLETE_WITH_CONST("ON");
1778 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1780 completion_info_charp = prev2_wd;
1781 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1785 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1787 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1788 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1790 /* ALTER TRIGGER <name> ON <name> */
1791 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1792 COMPLETE_WITH_CONST("RENAME TO");
1795 * If we detect ALTER TABLE <name>, suggest sub commands
1797 else if (Matches3("ALTER", "TABLE", MatchAny))
1799 static const char *const list_ALTER2[] =
1800 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1801 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1802 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", "ATTACH PARTITION",
1803 "DETACH PARTITION", NULL};
1805 COMPLETE_WITH_LIST(list_ALTER2);
1807 /* ALTER TABLE xxx ENABLE */
1808 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1809 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1811 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1812 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1813 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1815 completion_info_charp = prev3_wd;
1816 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1818 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1820 completion_info_charp = prev4_wd;
1821 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1823 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1825 completion_info_charp = prev3_wd;
1826 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1828 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1830 completion_info_charp = prev4_wd;
1831 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1833 /* ALTER TABLE xxx INHERIT */
1834 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1835 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1836 /* ALTER TABLE xxx NO INHERIT */
1837 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1838 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1839 /* ALTER TABLE xxx DISABLE */
1840 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1841 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1842 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1844 completion_info_charp = prev3_wd;
1845 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1847 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1849 completion_info_charp = prev3_wd;
1850 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1853 /* ALTER TABLE xxx ALTER */
1854 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1855 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1857 /* ALTER TABLE xxx RENAME */
1858 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1859 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1860 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1861 COMPLETE_WITH_ATTR(prev3_wd, "");
1863 /* ALTER TABLE xxx RENAME yyy */
1864 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1865 COMPLETE_WITH_CONST("TO");
1867 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1868 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1869 COMPLETE_WITH_CONST("TO");
1871 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1872 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1873 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1874 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1875 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1876 COMPLETE_WITH_ATTR(prev3_wd, "");
1879 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1880 * provide list of constraints
1882 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1884 completion_info_charp = prev3_wd;
1885 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1887 /* ALTER TABLE ALTER [COLUMN] <foo> */
1888 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1889 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1890 COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
1891 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1892 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1893 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1894 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1895 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1896 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1897 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1898 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1899 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1900 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1901 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1902 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1903 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1904 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1905 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1906 COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
1907 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1908 COMPLETE_WITH_CONST("ON");
1909 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1911 completion_info_charp = prev3_wd;
1912 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1914 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1915 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1916 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1920 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1923 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1924 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1925 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
1926 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
1927 COMPLETE_WITH_CONST("OIDS");
1928 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1929 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1930 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
1931 /* ALTER TABLE <foo> RESET */
1932 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
1933 COMPLETE_WITH_CONST("(");
1934 /* ALTER TABLE <foo> SET|RESET ( */
1935 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1937 static const char *const list_TABLEOPTIONS[] =
1939 "autovacuum_analyze_scale_factor",
1940 "autovacuum_analyze_threshold",
1941 "autovacuum_enabled",
1942 "autovacuum_freeze_max_age",
1943 "autovacuum_freeze_min_age",
1944 "autovacuum_freeze_table_age",
1945 "autovacuum_multixact_freeze_max_age",
1946 "autovacuum_multixact_freeze_min_age",
1947 "autovacuum_multixact_freeze_table_age",
1948 "autovacuum_vacuum_cost_delay",
1949 "autovacuum_vacuum_cost_limit",
1950 "autovacuum_vacuum_scale_factor",
1951 "autovacuum_vacuum_threshold",
1954 "log_autovacuum_min_duration",
1955 "toast.autovacuum_enabled",
1956 "toast.autovacuum_freeze_max_age",
1957 "toast.autovacuum_freeze_min_age",
1958 "toast.autovacuum_freeze_table_age",
1959 "toast.autovacuum_multixact_freeze_max_age",
1960 "toast.autovacuum_multixact_freeze_min_age",
1961 "toast.autovacuum_multixact_freeze_table_age",
1962 "toast.autovacuum_vacuum_cost_delay",
1963 "toast.autovacuum_vacuum_cost_limit",
1964 "toast.autovacuum_vacuum_scale_factor",
1965 "toast.autovacuum_vacuum_threshold",
1966 "toast.log_autovacuum_min_duration",
1967 "user_catalog_table",
1971 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
1973 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
1975 completion_info_charp = prev5_wd;
1976 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1978 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1979 COMPLETE_WITH_CONST("INDEX");
1980 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1981 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
1982 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
1983 COMPLETE_WITH_CONST("IDENTITY");
1985 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
1988 else if (Matches5("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
1989 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1990 /* Limited completion support for partition bound specification */
1991 else if (TailMatches3("ATTACH", "PARTITION", MatchAny))
1992 COMPLETE_WITH_CONST("FOR VALUES");
1993 else if (TailMatches2("FOR", "VALUES"))
1994 COMPLETE_WITH_LIST2("FROM (", "IN (");
1996 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
1997 * partitions of <foo>.
1999 else if (Matches5("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
2001 completion_info_charp = prev3_wd;
2002 COMPLETE_WITH_QUERY(Query_for_partition_of_table);
2005 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
2006 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
2007 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
2008 /* ALTER TABLESPACE <foo> SET|RESET */
2009 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
2010 COMPLETE_WITH_CONST("(");
2011 /* ALTER TABLESPACE <foo> SET|RESET ( */
2012 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
2013 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
2014 "effective_io_concurrency");
2016 /* ALTER TEXT SEARCH */
2017 else if (Matches3("ALTER", "TEXT", "SEARCH"))
2018 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2019 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
2020 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
2021 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
2022 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
2023 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2024 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
2026 "OWNER TO", "RENAME TO", "SET SCHEMA");
2028 /* complete ALTER TYPE <foo> with actions */
2029 else if (Matches3("ALTER", "TYPE", MatchAny))
2030 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
2032 "OWNER TO", "RENAME", "SET SCHEMA");
2033 /* complete ALTER TYPE <foo> ADD with actions */
2034 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
2035 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
2036 /* ALTER TYPE <foo> RENAME */
2037 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
2038 COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
2039 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
2040 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
2041 COMPLETE_WITH_CONST("TO");
2043 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
2046 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
2047 COMPLETE_WITH_ATTR(prev3_wd, "");
2048 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
2049 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
2050 COMPLETE_WITH_CONST("TYPE");
2051 /* complete ALTER GROUP <foo> */
2052 else if (Matches3("ALTER", "GROUP", MatchAny))
2053 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
2054 /* complete ALTER GROUP <foo> ADD|DROP with USER */
2055 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
2056 COMPLETE_WITH_CONST("USER");
2057 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
2058 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
2059 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2062 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
2064 else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
2065 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
2068 else if (Matches1("BEGIN"))
2069 COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2071 else if (Matches1("END|ABORT"))
2072 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
2074 else if (Matches1("COMMIT"))
2075 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
2076 /* RELEASE SAVEPOINT */
2077 else if (Matches1("RELEASE"))
2078 COMPLETE_WITH_CONST("SAVEPOINT");
2080 else if (Matches1("ROLLBACK"))
2081 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
2083 else if (Matches1("CLUSTER"))
2084 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
2085 else if (Matches2("CLUSTER", "VERBOSE"))
2086 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2087 /* If we have CLUSTER <sth>, then add "USING" */
2088 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
2089 COMPLETE_WITH_CONST("USING");
2090 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
2091 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
2092 COMPLETE_WITH_CONST("USING");
2093 /* If we have CLUSTER <sth> USING, then add the index as well */
2094 else if (Matches3("CLUSTER", MatchAny, "USING") ||
2095 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
2097 completion_info_charp = prev2_wd;
2098 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2102 else if (Matches1("COMMENT"))
2103 COMPLETE_WITH_CONST("ON");
2104 else if (Matches2("COMMENT", "ON"))
2106 static const char *const list_COMMENT[] =
2107 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
2108 "EVENT TRIGGER", "EXTENSION",
2109 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2110 "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
2111 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
2112 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
2113 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
2115 COMPLETE_WITH_LIST(list_COMMENT);
2117 else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
2118 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2119 else if (Matches3("COMMENT", "ON", "FOREIGN"))
2120 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2121 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
2122 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2123 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
2124 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
2125 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
2126 COMPLETE_WITH_CONST("ON");
2127 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2129 completion_info_charp = prev2_wd;
2130 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
2132 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
2133 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2134 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
2135 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2136 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
2137 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2138 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
2139 COMPLETE_WITH_CONST("IS");
2144 * If we have COPY, offer list of tables or "(" (Also cover the analogous
2145 * backslash command).
2147 else if (Matches1("COPY|\\copy"))
2148 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2149 " UNION ALL SELECT '('");
2150 /* If we have COPY BINARY, complete with list of tables */
2151 else if (Matches2("COPY", "BINARY"))
2152 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2153 /* If we have COPY (, complete it with legal commands */
2154 else if (Matches2("COPY|\\copy", "("))
2155 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
2156 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
2157 else if (Matches2("COPY|\\copy", MatchAny) ||
2158 Matches3("COPY", "BINARY", MatchAny))
2159 COMPLETE_WITH_LIST2("FROM", "TO");
2160 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
2161 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
2162 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
2164 completion_charp = "";
2165 matches = completion_matches(text, complete_from_files);
2168 /* Handle COPY [BINARY] <sth> FROM|TO filename */
2169 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
2170 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
2171 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
2174 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
2175 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
2176 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
2177 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
2180 /* CREATE ACCESS METHOD */
2181 /* Complete "CREATE ACCESS METHOD <name>" */
2182 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
2183 COMPLETE_WITH_CONST("TYPE");
2184 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
2185 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
2186 COMPLETE_WITH_CONST("INDEX");
2187 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
2188 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
2189 COMPLETE_WITH_CONST("HANDLER");
2191 /* CREATE DATABASE */
2192 else if (Matches3("CREATE", "DATABASE", MatchAny))
2193 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2195 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2196 "LC_COLLATE", "LC_CTYPE");
2198 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2199 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2201 /* CREATE EXTENSION */
2202 /* Complete with available extensions rather than installed ones. */
2203 else if (Matches2("CREATE", "EXTENSION"))
2204 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2205 /* CREATE EXTENSION <name> */
2206 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2207 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2208 /* CREATE EXTENSION <name> VERSION */
2209 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2211 completion_info_charp = prev2_wd;
2212 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2215 /* CREATE FOREIGN */
2216 else if (Matches2("CREATE", "FOREIGN"))
2217 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2219 /* CREATE FOREIGN DATA WRAPPER */
2220 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2221 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2223 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2224 /* First off we complete CREATE UNIQUE with "INDEX" */
2225 else if (TailMatches2("CREATE", "UNIQUE"))
2226 COMPLETE_WITH_CONST("INDEX");
2229 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2232 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2233 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2234 " UNION SELECT 'ON'"
2235 " UNION SELECT 'CONCURRENTLY'");
2236 /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
2237 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2238 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2239 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2242 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2245 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2246 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2247 " UNION SELECT 'ON'");
2248 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2249 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2250 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2251 COMPLETE_WITH_CONST("ON");
2254 * Complete INDEX <name> ON <table> with a list of table columns (which
2255 * should really be in parens)
2257 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2258 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2259 COMPLETE_WITH_LIST2("(", "USING");
2260 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2261 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2262 COMPLETE_WITH_ATTR(prev2_wd, "");
2263 /* same if you put in USING */
2264 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2265 COMPLETE_WITH_ATTR(prev4_wd, "");
2266 /* Complete USING with an index method */
2267 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2268 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2269 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2270 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2271 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2272 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2273 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2274 COMPLETE_WITH_CONST("(");
2277 /* Complete "CREATE POLICY <name> ON" */
2278 else if (Matches3("CREATE", "POLICY", MatchAny))
2279 COMPLETE_WITH_CONST("ON");
2280 /* Complete "CREATE POLICY <name> ON <table>" */
2281 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2282 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2283 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
2284 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2285 COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
2286 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
2287 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
2288 COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
2289 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR|TO|USING|WITH CHECK */
2290 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
2291 COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
2292 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2293 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2294 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2295 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2296 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2297 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2298 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2299 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2300 COMPLETE_WITH_LIST2("TO", "USING (");
2301 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2302 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2303 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2304 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2305 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2306 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2307 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2308 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2309 COMPLETE_WITH_CONST("(");
2310 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2311 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
2312 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2313 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR INSERT TO|WITH CHECK" */
2314 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
2315 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2316 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR SELECT|DELETE TO|USING" */
2317 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
2318 COMPLETE_WITH_LIST2("TO", "USING (");
2319 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR ALL|UPDATE TO|USING|WITH CHECK */
2320 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
2321 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2322 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO <role>" */
2323 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
2324 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2325 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE USING (" */
2326 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
2327 COMPLETE_WITH_CONST("(");
2330 /* CREATE PUBLICATION */
2331 else if (Matches3("CREATE", "PUBLICATION", MatchAny))
2332 COMPLETE_WITH_LIST3("FOR TABLE", "FOR ALL TABLES", "WITH (");
2333 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR"))
2334 COMPLETE_WITH_LIST2("TABLE", "ALL TABLES");
2335 /* Complete "CREATE PUBLICATION <name> FOR TABLE <table>" */
2336 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
2337 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2338 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
2339 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
2340 COMPLETE_WITH_LIST2("PUBLISH", "NOPUBLISH");
2341 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches3("WITH", "(", MatchAny))
2342 COMPLETE_WITH_LIST3("INSERT", "UPDATE", "DELETE");
2345 /* Complete "CREATE RULE <sth>" with "AS ON" */
2346 else if (Matches3("CREATE", "RULE", MatchAny))
2347 COMPLETE_WITH_CONST("AS ON");
2348 /* Complete "CREATE RULE <sth> AS" with "ON" */
2349 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2350 COMPLETE_WITH_CONST("ON");
2351 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2352 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2353 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2354 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2355 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2356 COMPLETE_WITH_CONST("TO");
2357 /* Complete "AS ON <sth> TO" with a table name */
2358 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2359 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2361 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2362 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2363 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2364 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2365 "CYCLE", "OWNED BY", "START WITH");
2366 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2367 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2368 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2370 /* CREATE SERVER <name> */
2371 else if (Matches3("CREATE", "SERVER", MatchAny))
2372 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2374 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2375 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2376 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2377 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2378 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2379 else if (TailMatches2("CREATE", "UNLOGGED"))
2380 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2381 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
2382 else if (TailMatches2("PARTITION", "BY"))
2383 COMPLETE_WITH_LIST2("RANGE (", "LIST (");
2384 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
2385 else if (TailMatches2("PARTITION", "OF"))
2386 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables, "");
2387 /* Limited completion support for partition bound specification */
2388 else if (TailMatches3("PARTITION", "OF", MatchAny))
2389 COMPLETE_WITH_CONST("FOR VALUES");
2391 /* CREATE TABLESPACE */
2392 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2393 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2394 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2395 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2396 COMPLETE_WITH_CONST("LOCATION");
2398 /* CREATE TEXT SEARCH */
2399 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2400 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2401 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2402 COMPLETE_WITH_CONST("(");
2404 /* CREATE SUBSCRIPTION */
2405 else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
2406 COMPLETE_WITH_CONST("CONNECTION");
2407 else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
2408 COMPLETE_WITH_CONST("PUBLICATION");
2409 else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
2410 MatchAny, "PUBLICATION"))
2412 /* complete with nothing here as this refers to remote publications */
2414 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
2415 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
2416 COMPLETE_WITH_LIST5("ENABLED", "DISABLED", "CREATE SLOT",
2417 "NOCREATE SLOT", "SLOT NAME");
2419 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2420 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2421 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2422 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2423 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2424 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2425 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2426 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2427 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2428 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2429 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2430 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2431 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2432 COMPLETE_WITH_LIST2("ON", "OR");
2435 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2438 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2439 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2440 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2441 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2442 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2443 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
2444 COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
2445 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2446 else if (HeadMatches2("CREATE", "TRIGGER") &&
2447 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
2448 COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2449 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
2450 COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
2451 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
2452 COMPLETE_WITH_CONST("AS");
2453 else if (HeadMatches2("CREATE", "TRIGGER") &&
2454 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
2455 TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
2456 COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2457 else if (HeadMatches2("CREATE", "TRIGGER") &&
2458 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
2459 TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
2460 COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2461 else if (HeadMatches2("CREATE", "TRIGGER") &&
2462 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2463 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2464 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
2465 TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
2466 COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
2467 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
2468 COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
2469 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
2470 COMPLETE_WITH_LIST2("ROW", "STATEMENT");
2471 else if (HeadMatches2("CREATE", "TRIGGER") &&
2472 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
2473 TailMatches2("FOR", "ROW|STATEMENT")))
2474 COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
2475 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2476 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2477 COMPLETE_WITH_CONST("PROCEDURE");
2478 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
2479 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2481 /* CREATE ROLE,USER,GROUP <name> */
2482 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2483 !TailMatches2("USER", "MAPPING"))
2485 static const char *const list_CREATEROLE[] =
2486 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2487 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2488 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2489 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2490 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2491 "VALID UNTIL", "WITH", NULL};
2493 COMPLETE_WITH_LIST(list_CREATEROLE);
2496 /* CREATE ROLE,USER,GROUP <name> WITH */
2497 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2499 /* Similar to the above, but don't complete "WITH" again. */
2500 static const char *const list_CREATEROLE_WITH[] =
2501 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2502 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2503 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2504 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2505 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2506 "VALID UNTIL", NULL};
2508 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2512 * complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
2515 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
2516 COMPLETE_WITH_CONST("PASSWORD");
2517 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2518 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2519 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2521 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2522 /* Complete CREATE VIEW <name> with AS */
2523 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2524 COMPLETE_WITH_CONST("AS");
2525 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2526 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2527 COMPLETE_WITH_CONST("SELECT");
2529 /* CREATE MATERIALIZED VIEW */
2530 else if (Matches2("CREATE", "MATERIALIZED"))
2531 COMPLETE_WITH_CONST("VIEW");
2532 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2533 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2534 COMPLETE_WITH_CONST("AS");
2535 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2536 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2537 COMPLETE_WITH_CONST("SELECT");
2539 /* CREATE EVENT TRIGGER */
2540 else if (Matches2("CREATE", "EVENT"))
2541 COMPLETE_WITH_CONST("TRIGGER");
2542 /* Complete CREATE EVENT TRIGGER <name> with ON */
2543 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2544 COMPLETE_WITH_CONST("ON");
2545 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2546 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2547 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2550 else if (Matches1("DEALLOCATE"))
2551 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2554 else if (Matches2("DECLARE", MatchAny))
2555 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2557 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2558 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2560 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2561 /* ... despite which, only complete DELETE with FROM at start of line */
2562 else if (Matches1("DELETE"))
2563 COMPLETE_WITH_CONST("FROM");
2564 /* Complete DELETE FROM with a list of tables */
2565 else if (TailMatches2("DELETE", "FROM"))
2566 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2567 /* Complete DELETE FROM <table> */
2568 else if (TailMatches3("DELETE", "FROM", MatchAny))
2569 COMPLETE_WITH_LIST2("USING", "WHERE");
2570 /* XXX: implement tab completion for DELETE ... USING */
2573 else if (Matches1("DISCARD"))
2574 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2577 else if (Matches1("DO"))
2578 COMPLETE_WITH_CONST("LANGUAGE");
2581 /* Complete DROP object with CASCADE / RESTRICT */
2582 else if (Matches3("DROP",
2583 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
2585 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2586 (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2587 ends_with(prev_wd, ')')) ||
2588 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2589 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2590 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2591 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2592 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2594 /* help completing some of the variants */
2595 else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2596 COMPLETE_WITH_CONST("(");
2597 else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2598 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2599 else if (Matches2("DROP", "FOREIGN"))
2600 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2603 else if (Matches2("DROP", "INDEX"))
2604 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2605 " UNION SELECT 'CONCURRENTLY'");
2606 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2607 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2608 else if (Matches3("DROP", "INDEX", MatchAny))
2609 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2610 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2611 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2613 /* DROP MATERIALIZED VIEW */
2614 else if (Matches2("DROP", "MATERIALIZED"))
2615 COMPLETE_WITH_CONST("VIEW");
2616 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2617 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2620 else if (Matches2("DROP", "OWNED"))
2621 COMPLETE_WITH_CONST("BY");
2622 else if (Matches3("DROP", "OWNED", "BY"))
2623 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2625 else if (Matches3("DROP", "TEXT", "SEARCH"))
2626 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2629 else if (Matches3("DROP", "TRIGGER", MatchAny))
2630 COMPLETE_WITH_CONST("ON");
2631 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2633 completion_info_charp = prev2_wd;
2634 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2636 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2637 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2639 /* DROP ACCESS METHOD */
2640 else if (Matches2("DROP", "ACCESS"))
2641 COMPLETE_WITH_CONST("METHOD");
2642 else if (Matches3("DROP", "ACCESS", "METHOD"))
2643 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2645 /* DROP EVENT TRIGGER */
2646 else if (Matches2("DROP", "EVENT"))
2647 COMPLETE_WITH_CONST("TRIGGER");
2648 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2649 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2651 /* DROP POLICY <name> */
2652 else if (Matches2("DROP", "POLICY"))
2653 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2654 /* DROP POLICY <name> ON */
2655 else if (Matches3("DROP", "POLICY", MatchAny))
2656 COMPLETE_WITH_CONST("ON");
2657 /* DROP POLICY <name> ON <table> */
2658 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2660 completion_info_charp = prev2_wd;
2661 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2665 else if (Matches3("DROP", "RULE", MatchAny))
2666 COMPLETE_WITH_CONST("ON");
2667 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2669 completion_info_charp = prev2_wd;
2670 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2672 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2673 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2676 else if (Matches1("EXECUTE"))
2677 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2682 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2684 else if (Matches1("EXPLAIN"))
2685 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2686 "ANALYZE", "VERBOSE");
2687 else if (Matches2("EXPLAIN", "ANALYZE"))
2688 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2690 else if (Matches2("EXPLAIN", "VERBOSE") ||
2691 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2692 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2695 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2696 else if (Matches1("FETCH|MOVE"))
2697 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2698 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2699 else if (Matches2("FETCH|MOVE", MatchAny))
2700 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2703 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2704 * but we may as well tab-complete both: perhaps some users prefer one
2705 * variant or the other.
2707 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2708 COMPLETE_WITH_LIST2("FROM", "IN");
2710 /* FOREIGN DATA WRAPPER */
2711 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2712 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2713 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2714 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2715 /* applies in CREATE SERVER */
2716 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2717 HeadMatches2("CREATE", "SERVER"))
2718 COMPLETE_WITH_CONST("OPTIONS");
2721 else if (TailMatches2("FOREIGN", "TABLE") &&
2722 !TailMatches3("CREATE", MatchAny, MatchAny))
2723 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2725 /* FOREIGN SERVER */
2726 else if (TailMatches2("FOREIGN", "SERVER"))
2727 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2730 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
2731 * ALTER DEFAULT PRIVILEGES, so use TailMatches
2733 /* Complete GRANT/REVOKE with a list of roles and privileges */
2734 else if (TailMatches1("GRANT|REVOKE"))
2736 * With ALTER DEFAULT PRIVILEGES, restrict completion
2737 * to grantable privileges (can't grant roles)
2739 if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
2740 COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
2741 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
2742 "EXECUTE", "USAGE", "ALL");
2744 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2745 " UNION SELECT 'SELECT'"
2746 " UNION SELECT 'INSERT'"
2747 " UNION SELECT 'UPDATE'"
2748 " UNION SELECT 'DELETE'"
2749 " UNION SELECT 'TRUNCATE'"
2750 " UNION SELECT 'REFERENCES'"
2751 " UNION SELECT 'TRIGGER'"
2752 " UNION SELECT 'CREATE'"
2753 " UNION SELECT 'CONNECT'"
2754 " UNION SELECT 'TEMPORARY'"
2755 " UNION SELECT 'EXECUTE'"
2756 " UNION SELECT 'USAGE'"
2757 " UNION SELECT 'ALL'");
2760 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2763 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2765 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2766 COMPLETE_WITH_CONST("ON");
2767 else if (TailMatches2("GRANT", MatchAny))
2768 COMPLETE_WITH_CONST("TO");
2770 COMPLETE_WITH_CONST("FROM");
2774 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2777 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2778 * result via UNION; seems to work intuitively.
2780 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2781 * here will only work if the privilege list contains exactly one
2784 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2786 * With ALTER DEFAULT PRIVILEGES, restrict completion
2787 * to the kinds of objects supported.
2789 if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
2790 COMPLETE_WITH_LIST4("TABLES", "SEQUENCES", "FUNCTIONS", "TYPES");
2792 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2793 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2794 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2795 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2796 " UNION SELECT 'DATABASE'"
2797 " UNION SELECT 'DOMAIN'"
2798 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2799 " UNION SELECT 'FOREIGN SERVER'"
2800 " UNION SELECT 'FUNCTION'"
2801 " UNION SELECT 'LANGUAGE'"
2802 " UNION SELECT 'LARGE OBJECT'"
2803 " UNION SELECT 'SCHEMA'"
2804 " UNION SELECT 'SEQUENCE'"
2805 " UNION SELECT 'TABLE'"
2806 " UNION SELECT 'TABLESPACE'"
2807 " UNION SELECT 'TYPE'");
2809 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2810 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2811 "TABLES IN SCHEMA");
2813 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2814 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2817 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2818 * appropriate objects.
2820 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2822 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2824 if (TailMatches1("DATABASE"))
2825 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2826 else if (TailMatches1("DOMAIN"))
2827 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2828 else if (TailMatches1("FUNCTION"))
2829 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2830 else if (TailMatches1("LANGUAGE"))
2831 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2832 else if (TailMatches1("SCHEMA"))
2833 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2834 else if (TailMatches1("SEQUENCE"))
2835 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2836 else if (TailMatches1("TABLE"))
2837 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2838 else if (TailMatches1("TABLESPACE"))
2839 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2840 else if (TailMatches1("TYPE"))
2841 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2842 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2843 COMPLETE_WITH_CONST("TO");
2845 COMPLETE_WITH_CONST("FROM");
2849 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2850 * CURRENT_USER, or SESSION_USER.
2852 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2853 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2854 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2855 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
2856 else if (HeadMatches3("ALTER","DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
2857 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2858 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2859 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2860 COMPLETE_WITH_CONST("TO");
2861 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2862 COMPLETE_WITH_CONST("FROM");
2864 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2865 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2867 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2868 COMPLETE_WITH_CONST("TO");
2870 COMPLETE_WITH_CONST("FROM");
2873 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2874 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2876 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2877 COMPLETE_WITH_CONST("TO");
2879 COMPLETE_WITH_CONST("FROM");
2882 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
2883 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
2885 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2886 COMPLETE_WITH_CONST("TO");
2888 COMPLETE_WITH_CONST("FROM");
2892 else if (TailMatches3("FROM", MatchAny, "GROUP"))
2893 COMPLETE_WITH_CONST("BY");
2895 /* IMPORT FOREIGN SCHEMA */
2896 else if (Matches1("IMPORT"))
2897 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
2898 else if (Matches2("IMPORT", "FOREIGN"))
2899 COMPLETE_WITH_CONST("SCHEMA");
2901 /* INSERT --- can be inside EXPLAIN, RULE, etc */
2902 /* Complete INSERT with "INTO" */
2903 else if (TailMatches1("INSERT"))
2904 COMPLETE_WITH_CONST("INTO");
2905 /* Complete INSERT INTO with table names */
2906 else if (TailMatches2("INSERT", "INTO"))
2907 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2908 /* Complete "INSERT INTO <table> (" with attribute names */
2909 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
2910 COMPLETE_WITH_ATTR(prev2_wd, "");
2913 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2914 * "TABLE" or "DEFAULT VALUES"
2916 else if (TailMatches3("INSERT", "INTO", MatchAny))
2917 COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
2920 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
2923 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
2924 ends_with(prev_wd, ')'))
2925 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
2927 /* Insert an open parenthesis after "VALUES" */
2928 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
2929 COMPLETE_WITH_CONST("(");
2932 /* Complete LOCK [TABLE] with a list of tables */
2933 else if (Matches1("LOCK"))
2934 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2935 " UNION SELECT 'TABLE'");
2936 else if (Matches2("LOCK", "TABLE"))
2937 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2939 /* For the following, handle the case of a single table only for now */
2941 /* Complete LOCK [TABLE] <table> with "IN" */
2942 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
2943 Matches3("LOCK", "TABLE", MatchAny))
2944 COMPLETE_WITH_CONST("IN");
2946 /* Complete LOCK [TABLE] <table> IN with a lock mode */
2947 else if (Matches3("LOCK", MatchAny, "IN") ||
2948 Matches4("LOCK", "TABLE", MatchAny, "IN"))
2949 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
2950 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
2951 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
2952 "SHARE ROW EXCLUSIVE MODE",
2953 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
2955 /* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
2956 else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
2957 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
2958 COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
2960 /* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
2961 else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
2962 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
2963 COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
2964 "UPDATE EXCLUSIVE MODE");
2966 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
2967 else if (TailMatches1("NOTIFY"))
2968 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'");
2971 else if (TailMatches1("OPTIONS"))
2972 COMPLETE_WITH_CONST("(");
2974 /* OWNER TO - complete with available roles */
2975 else if (TailMatches2("OWNER", "TO"))
2976 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2979 else if (TailMatches3("FROM", MatchAny, "ORDER"))
2980 COMPLETE_WITH_CONST("BY");
2981 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
2982 COMPLETE_WITH_ATTR(prev3_wd, "");
2985 else if (Matches3("PREPARE", MatchAny, "AS"))
2986 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
2989 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
2990 * managers, not for manual use in interactive sessions.
2993 /* REASSIGN OWNED BY xxx TO yyy */
2994 else if (Matches1("REASSIGN"))
2995 COMPLETE_WITH_CONST("OWNED BY");
2996 else if (Matches2("REASSIGN", "OWNED"))
2997 COMPLETE_WITH_CONST("BY");
2998 else if (Matches3("REASSIGN", "OWNED", "BY"))
2999 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3000 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
3001 COMPLETE_WITH_CONST("TO");
3002 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
3003 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3005 /* REFRESH MATERIALIZED VIEW */
3006 else if (Matches1("REFRESH"))
3007 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
3008 else if (Matches2("REFRESH", "MATERIALIZED"))
3009 COMPLETE_WITH_CONST("VIEW");
3010 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
3011 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
3012 " UNION SELECT 'CONCURRENTLY'");
3013 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
3014 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3015 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
3016 COMPLETE_WITH_CONST("WITH");
3017 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
3018 COMPLETE_WITH_CONST("WITH");
3019 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
3020 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3021 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
3022 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3023 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
3024 COMPLETE_WITH_CONST("DATA");
3025 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
3026 COMPLETE_WITH_CONST("DATA");
3029 else if (Matches1("REINDEX"))
3030 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
3031 else if (Matches2("REINDEX", "TABLE"))
3032 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3033 else if (Matches2("REINDEX", "INDEX"))
3034 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3035 else if (Matches2("REINDEX", "SCHEMA"))
3036 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3037 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
3038 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3040 /* SECURITY LABEL */
3041 else if (Matches1("SECURITY"))
3042 COMPLETE_WITH_CONST("LABEL");
3043 else if (Matches2("SECURITY", "LABEL"))
3044 COMPLETE_WITH_LIST2("ON", "FOR");
3045 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
3046 COMPLETE_WITH_CONST("ON");
3047 else if (Matches3("SECURITY", "LABEL", "ON") ||
3048 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
3050 static const char *const list_SECURITY_LABEL[] =
3051 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
3052 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
3053 "MATERIALIZED VIEW", "LANGUAGE", "ROLE", "SCHEMA",
3054 "SEQUENCE", "TABLESPACE", "TYPE", "VIEW", NULL};
3056 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
3058 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
3059 COMPLETE_WITH_CONST("IS");
3064 /* SET, RESET, SHOW */
3065 /* Complete with a variable name */
3066 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
3067 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
3068 else if (Matches1("SHOW"))
3069 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
3070 /* Complete "SET TRANSACTION" */
3071 else if (Matches2("SET", "TRANSACTION"))
3072 COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3073 else if (Matches2("BEGIN|START", "TRANSACTION") ||
3074 Matches2("BEGIN", "WORK") ||
3075 Matches1("BEGIN") ||
3076 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
3077 COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3078 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
3079 Matches2("BEGIN", "NOT") ||
3080 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
3081 COMPLETE_WITH_CONST("DEFERRABLE");
3082 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
3083 Matches2("BEGIN", "ISOLATION") ||
3084 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
3085 COMPLETE_WITH_CONST("LEVEL");
3086 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
3087 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
3088 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
3089 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
3090 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
3091 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
3092 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
3093 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
3094 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
3095 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
3096 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
3097 COMPLETE_WITH_CONST("READ");
3098 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
3099 Matches2("BEGIN", "READ") ||
3100 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
3101 COMPLETE_WITH_LIST2("ONLY", "WRITE");
3102 /* SET CONSTRAINTS */
3103 else if (Matches2("SET", "CONSTRAINTS"))
3104 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
3105 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
3106 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
3107 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
3108 /* Complete SET ROLE */
3109 else if (Matches2("SET", "ROLE"))
3110 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3111 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
3112 else if (Matches2("SET", "SESSION"))
3113 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
3114 /* Complete SET SESSION AUTHORIZATION with username */
3115 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
3116 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
3117 /* Complete RESET SESSION with AUTHORIZATION */
3118 else if (Matches2("RESET", "SESSION"))
3119 COMPLETE_WITH_CONST("AUTHORIZATION");
3120 /* Complete SET <var> with "TO" */
3121 else if (Matches2("SET", MatchAny))
3122 COMPLETE_WITH_CONST("TO");
3123 /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
3124 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
3125 TailMatches2("SET", MatchAny))
3126 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
3127 /* Suggest possible variable values */
3128 else if (TailMatches3("SET", MatchAny, "TO|="))
3130 /* special cased code for individual GUCs */
3131 if (TailMatches2("DateStyle", "TO|="))
3133 static const char *const my_list[] =
3134 {"ISO", "SQL", "Postgres", "German",
3135 "YMD", "DMY", "MDY",
3136 "US", "European", "NonEuropean",
3139 COMPLETE_WITH_LIST(my_list);
3141 else if (TailMatches2("search_path", "TO|="))
3142 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
3143 " AND nspname not like 'pg\\_toast%%' "
3144 " AND nspname not like 'pg\\_temp%%' "
3145 " UNION SELECT 'DEFAULT' ");
3148 /* generic, type based, GUC support */
3149 char *guctype = get_guctype(prev2_wd);
3151 if (guctype && strcmp(guctype, "enum") == 0)
3153 char querybuf[1024];
3155 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
3156 COMPLETE_WITH_QUERY(querybuf);
3158 else if (guctype && strcmp(guctype, "bool") == 0)
3159 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
3160 "1", "0", "DEFAULT");
3162 COMPLETE_WITH_CONST("DEFAULT");
3169 /* START TRANSACTION */
3170 else if (Matches1("START"))
3171 COMPLETE_WITH_CONST("TRANSACTION");
3173 /* TABLE, but not TABLE embedded in other commands */
3174 else if (Matches1("TABLE"))
3175 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3178 else if (TailMatches1("TABLESAMPLE"))
3179 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
3180 else if (TailMatches2("TABLESAMPLE", MatchAny))
3181 COMPLETE_WITH_CONST("(");
3184 else if (Matches1("TRUNCATE"))
3185 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3188 else if (Matches1("UNLISTEN"))
3189 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 '*'");
3191 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
3192 /* If prev. word is UPDATE suggest a list of tables */
3193 else if (TailMatches1("UPDATE"))
3194 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3195 /* Complete UPDATE <table> with "SET" */
3196 else if (TailMatches2("UPDATE", MatchAny))
3197 COMPLETE_WITH_CONST("SET");
3198 /* Complete UPDATE <table> SET with list of attributes */
3199 else if (TailMatches3("UPDATE", MatchAny, "SET"))
3200 COMPLETE_WITH_ATTR(prev2_wd, "");
3201 /* UPDATE <table> SET <attr> = */
3202 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
3203 COMPLETE_WITH_CONST("=");
3206 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
3207 COMPLETE_WITH_CONST("FOR");
3208 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
3209 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3210 " UNION SELECT 'CURRENT_USER'"
3211 " UNION SELECT 'PUBLIC'"
3212 " UNION SELECT 'USER'");
3213 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
3214 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3215 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
3216 COMPLETE_WITH_CONST("SERVER");
3217 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
3218 COMPLETE_WITH_CONST("OPTIONS");
3221 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
3222 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
3224 else if (Matches1("VACUUM"))
3225 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3226 " UNION SELECT 'FULL'"
3227 " UNION SELECT 'FREEZE'"
3228 " UNION SELECT 'ANALYZE'"
3229 " UNION SELECT 'VERBOSE'");
3230 else if (Matches2("VACUUM", "FULL|FREEZE"))
3231 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3232 " UNION SELECT 'ANALYZE'"
3233 " UNION SELECT 'VERBOSE'");
3234 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
3235 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3236 " UNION SELECT 'VERBOSE'");
3237 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
3238 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3239 " UNION SELECT 'ANALYZE'");
3240 else if (Matches2("VACUUM", "VERBOSE"))
3241 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3242 " UNION SELECT 'ANALYZE'");
3243 else if (Matches2("VACUUM", "ANALYZE"))
3244 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3245 " UNION SELECT 'VERBOSE'");
3246 else if (HeadMatches1("VACUUM"))
3247 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3249 /* WITH [RECURSIVE] */
3252 * Only match when WITH is the first word, as WITH may appear in many
3255 else if (Matches1("WITH"))
3256 COMPLETE_WITH_CONST("RECURSIVE");
3259 /* Complete with list of tables */
3260 else if (Matches1("ANALYZE"))
3261 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
3264 /* Simple case of the word before the where being the table name */
3265 else if (TailMatches2(MatchAny, "WHERE"))
3266 COMPLETE_WITH_ATTR(prev2_wd, "");
3269 /* TODO: also include SRF ? */
3270 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
3271 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3274 else if (TailMatches1("JOIN"))
3275 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3277 /* Backslash commands */
3278 /* TODO: \dc \dd \dl */
3279 else if (TailMatchesCS1("\\?"))
3280 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
3281 else if (TailMatchesCS1("\\connect|\\c"))
3283 if (!recognized_connection_string(text))
3284 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3286 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
3288 if (!recognized_connection_string(prev_wd))
3289 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3291 else if (TailMatchesCS1("\\da*"))
3292 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
3293 else if (TailMatchesCS1("\\dA*"))
3294 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3295 else if (TailMatchesCS1("\\db*"))
3296 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3297 else if (TailMatchesCS1("\\dD*"))
3298 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3299 else if (TailMatchesCS1("\\des*"))
3300 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3301 else if (TailMatchesCS1("\\deu*"))
3302 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3303 else if (TailMatchesCS1("\\dew*"))
3304 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3305 else if (TailMatchesCS1("\\df*"))
3306 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3308 else if (TailMatchesCS1("\\dFd*"))
3309 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
3310 else if (TailMatchesCS1("\\dFp*"))
3311 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
3312 else if (TailMatchesCS1("\\dFt*"))
3313 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
3314 /* must be at end of \dF alternatives: */
3315 else if (TailMatchesCS1("\\dF*"))
3316 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
3318 else if (TailMatchesCS1("\\di*"))
3319 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3320 else if (TailMatchesCS1("\\dL*"))
3321 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3322 else if (TailMatchesCS1("\\dn*"))
3323 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3324 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
3325 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3326 else if (TailMatchesCS1("\\ds*"))
3327 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3328 else if (TailMatchesCS1("\\dt*"))
3329 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3330 else if (TailMatchesCS1("\\dT*"))
3331 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3332 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
3333 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3334 else if (TailMatchesCS1("\\dv*"))
3335 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3336 else if (TailMatchesCS1("\\dx*"))
3337 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
3338 else if (TailMatchesCS1("\\dm*"))
3339 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3340 else if (TailMatchesCS1("\\dE*"))
3341 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3342 else if (TailMatchesCS1("\\dy*"))
3343 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3345 /* must be at end of \d alternatives: */
3346 else if (TailMatchesCS1("\\d*"))
3347 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3349 else if (TailMatchesCS1("\\ef"))
3350 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3351 else if (TailMatchesCS1("\\ev"))
3352 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3354 else if (TailMatchesCS1("\\encoding"))
3355 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3356 else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
3357 COMPLETE_WITH_LIST(sql_commands);
3358 else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
3359 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3360 else if (TailMatchesCS1("\\password"))
3361 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3362 else if (TailMatchesCS1("\\pset"))
3364 static const char *const my_list[] =
3365 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3366 "footer", "format", "linestyle", "null", "numericlocale",
3367 "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3368 "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3369 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3371 COMPLETE_WITH_LIST_CS(my_list);
3373 else if (TailMatchesCS2("\\pset", MatchAny))
3375 if (TailMatchesCS1("format"))
3377 static const char *const my_list[] =
3378 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3379 "latex", "latex-longtable", "troff-ms", NULL};
3381 COMPLETE_WITH_LIST_CS(my_list);
3383 else if (TailMatchesCS1("linestyle"))
3384 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3385 else if (TailMatchesCS1("unicode_border_linestyle|"
3386 "unicode_column_linestyle|"
3387 "unicode_header_linestyle"))
3388 COMPLETE_WITH_LIST_CS2("single", "double");
3390 else if (TailMatchesCS1("\\unset"))
3392 matches = complete_from_variables(text, "", "", true);
3394 else if (TailMatchesCS1("\\set"))
3396 matches = complete_from_variables(text, "", "", false);
3398 else if (TailMatchesCS2("\\set", MatchAny))
3400 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3401 "SINGLELINE|SINGLESTEP"))
3402 COMPLETE_WITH_LIST_CS2("on", "off");
3403 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3404 COMPLETE_WITH_LIST_CS4("lower", "upper",
3405 "preserve-lower", "preserve-upper");
3406 else if (TailMatchesCS1("ECHO"))
3407 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3408 else if (TailMatchesCS1("ECHO_HIDDEN"))
3409 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3410 else if (TailMatchesCS1("HISTCONTROL"))
3411 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3412 "ignoreboth", "none");
3413 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3414 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3415 else if (TailMatchesCS1("SHOW_CONTEXT"))
3416 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3417 else if (TailMatchesCS1("VERBOSITY"))
3418 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3420 else if (TailMatchesCS1("\\sf*"))
3421 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3422 else if (TailMatchesCS1("\\sv*"))
3423 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3424 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3425 "\\ir|\\include_relative|\\o|\\out|"
3426 "\\s|\\w|\\write|\\lo_import"))
3428 completion_charp = "\\";
3429 matches = completion_matches(text, complete_from_files);
3433 * Finally, we look through the list of "things", such as TABLE, INDEX and
3434 * check if that was the previous word. If so, execute the query to get a
3441 for (i = 0; words_after_create[i].name; i++)
3443 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3445 if (words_after_create[i].query)
3446 COMPLETE_WITH_QUERY(words_after_create[i].query);
3447 else if (words_after_create[i].squery)
3448 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3456 * If we still don't have anything to match we have to fabricate some sort
3457 * of default list. If we were to just return NULL, readline automatically
3458 * attempts filename completion, and that's usually no good.
3460 if (matches == NULL)
3462 COMPLETE_WITH_CONST("");
3463 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3464 rl_completion_append_character = '\0';
3469 free(previous_words);
3472 /* Return our Grand List O' Matches */
3478 * GENERATOR FUNCTIONS
3480 * These functions do all the actual work of completing the input. They get
3481 * passed the text so far and the count how many times they have been called
3482 * so far with the same text.
3483 * If you read the above carefully, you'll see that these don't get called
3484 * directly but through the readline interface.
3485 * The return value is expected to be the full completion of the text, going
3486 * through a list each time, or NULL if there are no more matches. The string
3487 * will be free()'d by readline, so you must run it through strdup() or
3488 * something of that sort.
3492 * Common routine for create_command_generator and drop_command_generator.
3493 * Entries that have 'excluded' flags are not returned.
3496 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3498 static int list_index,
3502 /* If this is the first time for this completion, init some values */
3506 string_length = strlen(text);
3509 /* find something that matches */
3510 while ((name = words_after_create[list_index++].name))
3512 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3513 !(words_after_create[list_index - 1].flags & excluded))
3514 return pg_strdup_keyword_case(name, text);
3516 /* if nothing matches, return NULL */
3521 * This one gives you one from a list of things you can put after CREATE
3525 create_command_generator(const char *text, int state)
3527 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3531 * This function gives you a list of things you can put after a DROP command.
3534 drop_command_generator(const char *text, int state)
3536 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3539 /* The following two functions are wrappers for _complete_from_query */
3542 complete_from_query(const char *text, int state)
3544 return _complete_from_query(0, text, state);
3548 complete_from_schema_query(const char *text, int state)
3550 return _complete_from_query(1, text, state);
3555 * This creates a list of matching things, according to a query pointed to
3556 * by completion_charp.
3557 * The query can be one of two kinds:
3559 * 1. A simple query which must contain a %d and a %s, which will be replaced
3560 * by the string length of the text and the text itself. The query may also
3561 * have up to four more %s in it; the first two such will be replaced by the
3562 * value of completion_info_charp, the next two by the value of
3563 * completion_info_charp2.
3565 * 2. A schema query used for completion of both schema and relation names.
3566 * These are more complex and must contain in the following order:
3567 * %d %s %d %s %d %s %s %d %s
3568 * where %d is the string length of the text and %s the text itself.
3570 * It is assumed that strings should be escaped to become SQL literals
3571 * (that is, what is in the query is actually ... '%s' ...)
3573 * See top of file for examples of both kinds of query.
3576 _complete_from_query(int is_schema_query, const char *text, int state)
3578 static int list_index,
3580 static PGresult *result = NULL;
3583 * If this is the first time for this completion, we fetch a list of our
3584 * "things" from the backend.
3588 PQExpBufferData query_buffer;
3591 char *e_info_charp2;
3592 const char *pstr = text;
3593 int char_length = 0;
3596 byte_length = strlen(text);
3599 * Count length as number of characters (not bytes), for passing to
3605 pstr += PQmblen(pstr, pset.encoding);
3608 /* Free any prior result */
3612 /* Set up suitably-escaped copies of textual inputs */
3613 e_text = escape_string(text);
3615 if (completion_info_charp)
3616 e_info_charp = escape_string(completion_info_charp);
3618 e_info_charp = NULL;
3620 if (completion_info_charp2)
3621 e_info_charp2 = escape_string(completion_info_charp2);
3623 e_info_charp2 = NULL;
3625 initPQExpBuffer(&query_buffer);
3627 if (is_schema_query)
3629 /* completion_squery gives us the pieces to assemble */
3630 const char *qualresult = completion_squery->qualresult;
3632 if (qualresult == NULL)
3633 qualresult = completion_squery->result;
3635 /* Get unqualified names matching the input-so-far */
3636 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3637 completion_squery->result,
3638 completion_squery->catname);
3639 if (completion_squery->selcondition)
3640 appendPQExpBuffer(&query_buffer, "%s AND ",
3641 completion_squery->selcondition);
3642 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3643 completion_squery->result,
3644 char_length, e_text);
3645 appendPQExpBuffer(&query_buffer, " AND %s",
3646 completion_squery->viscondition);
3649 * When fetching relation names, suppress system catalogs unless
3650 * the input-so-far begins with "pg_". This is a compromise
3651 * between not offering system catalogs for completion at all, and
3652 * having them swamp the result when the input is just "p".
3654 if (strcmp(completion_squery->catname,
3655 "pg_catalog.pg_class c") == 0 &&
3656 strncmp(text, "pg_", 3) !=0)
3658 appendPQExpBufferStr(&query_buffer,
3659 " AND c.relnamespace <> (SELECT oid FROM"
3660 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3664 * Add in matching schema names, but only if there is more than
3665 * one potential match among schema names.
3667 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3668 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3669 "FROM pg_catalog.pg_namespace n "
3670 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3671 char_length, e_text);
3672 appendPQExpBuffer(&query_buffer,
3673 " AND (SELECT pg_catalog.count(*)"
3674 " FROM pg_catalog.pg_namespace"
3675 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3676 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3677 char_length, e_text);
3680 * Add in matching qualified names, but only if there is exactly
3681 * one schema matching the input-so-far.
3683 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3684 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3685 "FROM %s, pg_catalog.pg_namespace n "
3686 "WHERE %s = n.oid AND ",
3688 completion_squery->catname,
3689 completion_squery->namespace);
3690 if (completion_squery->selcondition)
3691 appendPQExpBuffer(&query_buffer, "%s AND ",
3692 completion_squery->selcondition);
3693 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3695 char_length, e_text);
3698 * This condition exploits the single-matching-schema rule to
3699 * speed up the query
3701 appendPQExpBuffer(&query_buffer,
3702 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3703 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3704 char_length, e_text);
3705 appendPQExpBuffer(&query_buffer,
3706 " AND (SELECT pg_catalog.count(*)"
3707 " FROM pg_catalog.pg_namespace"
3708 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3709 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3710 char_length, e_text);
3712 /* If an addon query was provided, use it */
3713 if (completion_charp)
3714 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3718 /* completion_charp is an sprintf-style format string */
3719 appendPQExpBuffer(&query_buffer, completion_charp,
3720 char_length, e_text,
3721 e_info_charp, e_info_charp,
3722 e_info_charp2, e_info_charp2);
3725 /* Limit the number of records in the result */
3726 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3727 completion_max_records);
3729 result = exec_query(query_buffer.data);
3731 termPQExpBuffer(&query_buffer);
3736 free(e_info_charp2);
3739 /* Find something that matches */
3740 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3744 while (list_index < PQntuples(result) &&
3745 (item = PQgetvalue(result, list_index++, 0)))
3746 if (pg_strncasecmp(text, item, byte_length) == 0)
3747 return pg_strdup(item);
3750 /* If nothing matches, free the db structure and return null */
3758 * This function returns in order one of a fixed, NULL pointer terminated list
3759 * of strings (if matching). This can be used if there are only a fixed number
3760 * SQL words that can appear at certain spot.
3763 complete_from_list(const char *text, int state)
3765 static int string_length,
3768 static bool casesensitive;
3771 /* need to have a list */
3772 Assert(completion_charpp != NULL);
3774 /* Initialization */
3778 string_length = strlen(text);
3779 casesensitive = completion_case_sensitive;
3783 while ((item = completion_charpp[list_index++]))
3785 /* First pass is case sensitive */
3786 if (casesensitive && strncmp(text, item, string_length) == 0)
3789 return pg_strdup(item);
3792 /* Second pass is case insensitive, don't bother counting matches */
3793 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3795 if (completion_case_sensitive)
3796 return pg_strdup(item);
3800 * If case insensitive matching was requested initially,
3801 * adjust the case according to setting.
3803 return pg_strdup_keyword_case(item, text);
3808 * No matches found. If we're not case insensitive already, lets switch to
3809 * being case insensitive and try again
3811 if (casesensitive && matches == 0)
3813 casesensitive = false;
3816 return complete_from_list(text, state);
3819 /* If no more matches, return null. */
3825 * This function returns one fixed string the first time even if it doesn't
3826 * match what's there, and nothing the second time. This should be used if
3827 * there is only one possibility that can appear at a certain spot, so
3828 * misspellings will be overwritten. The string to be passed must be in
3832 complete_from_const(const char *text, int state)
3834 Assert(completion_charp != NULL);
3837 if (completion_case_sensitive)
3838 return pg_strdup(completion_charp);
3842 * If case insensitive matching was requested initially, adjust
3843 * the case according to setting.
3845 return pg_strdup_keyword_case(completion_charp, text);
3853 * This function appends the variable name with prefix and suffix to
3854 * the variable names array.
3857 append_variable_names(char ***varnames, int *nvars,
3858 int *maxvars, const char *varname,
3859 const char *prefix, const char *suffix)
3861 if (*nvars >= *maxvars)
3864 *varnames = (char **) pg_realloc(*varnames,
3865 ((*maxvars) + 1) * sizeof(char *));
3868 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3873 * This function supports completion with the name of a psql variable.
3874 * The variable names can be prefixed and suffixed with additional text
3875 * to support quoting usages. If need_value is true, only variables
3876 * that are currently set are included; otherwise, special variables
3877 * (those that have hooks) are included even if currently unset.
3880 complete_from_variables(const char *text, const char *prefix, const char *suffix,
3888 struct _variable *ptr;
3890 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
3892 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3894 if (need_value && !(ptr->value))
3896 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3900 varnames[nvars] = NULL;
3901 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
3903 for (i = 0; i < nvars; i++)
3912 * This function wraps rl_filename_completion_function() to strip quotes from
3913 * the input before searching for matches and to quote any matches for which
3914 * the consuming command will require it.
3917 complete_from_files(const char *text, int state)
3919 static const char *unquoted_text;
3920 char *unquoted_match;
3925 /* Initialization: stash the unquoted input. */
3926 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
3927 false, true, pset.encoding);
3928 /* expect a NULL return for the empty string only */
3931 Assert(*text == '\0');
3932 unquoted_text = text;
3936 unquoted_match = filename_completion_function(unquoted_text, state);
3940 * Caller sets completion_charp to a zero- or one-character string
3941 * containing the escape character. This is necessary since \copy has
3942 * no escape character, but every other backslash command recognizes
3943 * "\" as an escape character. Since we have only two callers, don't
3944 * bother providing a macro to simplify this.
3946 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
3947 '\'', *completion_charp, pset.encoding);
3949 free(unquoted_match);
3951 ret = unquoted_match;
3958 /* HELPER FUNCTIONS */
3962 * Make a pg_strdup copy of s and convert the case according to
3963 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
3966 pg_strdup_keyword_case(const char *s, const char *ref)
3970 unsigned char first = ref[0];
3974 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
3975 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
3976 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
3977 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
3979 for (p = ret; *p; p++)
3980 *p = pg_tolower((unsigned char) *p);
3984 for (p = ret; *p; p++)
3985 *p = pg_toupper((unsigned char) *p);
3993 * escape_string - Escape argument for use as string literal.
3995 * The returned value has to be freed.
3998 escape_string(const char *text)
4003 text_length = strlen(text);
4005 result = pg_malloc(text_length * 2 + 1);
4006 PQescapeStringConn(pset.db, result, text, text_length, NULL);
4013 * Execute a query and report any errors. This should be the preferred way of
4014 * talking to the database in this file.
4017 exec_query(const char *query)
4021 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
4024 result = PQexec(pset.db, query);
4026 if (PQresultStatus(result) != PGRES_TUPLES_OK)
4029 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
4030 PQerrorMessage(pset.db), query);
4041 * Parse all the word(s) before point.
4043 * Returns a malloc'd array of character pointers that point into the malloc'd
4044 * data array returned to *buffer; caller must free() both of these when done.
4045 * *nwords receives the number of words found, ie, the valid length of the
4048 * Words are returned right to left, that is, previous_words[0] gets the last
4049 * word before point, previous_words[1] the next-to-last, etc.
4052 get_previous_words(int point, char **buffer, int *nwords)
4054 char **previous_words;
4057 int words_found = 0;
4061 * If we have anything in tab_completion_query_buf, paste it together with
4062 * rl_line_buffer to construct the full query. Otherwise we can just use
4063 * rl_line_buffer as the input string.
4065 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
4067 i = tab_completion_query_buf->len;
4068 buf = pg_malloc(point + i + 2);
4069 memcpy(buf, tab_completion_query_buf->data, i);
4071 memcpy(buf + i, rl_line_buffer, point);
4074 /* Readjust point to reference appropriate offset in buf */
4078 buf = rl_line_buffer;
4081 * Allocate an array of string pointers and a buffer to hold the strings
4082 * themselves. The worst case is that the line contains only
4083 * non-whitespace WORD_BREAKS characters, making each one a separate word.
4084 * This is usually much more space than we need, but it's cheaper than
4085 * doing a separate malloc() for each word.
4087 previous_words = (char **) pg_malloc(point * sizeof(char *));
4088 *buffer = outptr = (char *) pg_malloc(point * 2);
4091 * First we look for a non-word char before the current point. (This is
4092 * probably useless, if readline is on the same page as we are about what
4093 * is a word, but if so it's cheap.)
4095 for (i = point - 1; i >= 0; i--)
4097 if (strchr(WORD_BREAKS, buf[i]))
4103 * Now parse words, working backwards, until we hit start of line. The
4104 * backwards scan has some interesting but intentional properties
4105 * concerning parenthesis handling.
4111 bool inquotes = false;
4112 int parentheses = 0;
4114 /* now find the first non-space which then constitutes the end */
4116 for (i = point; i >= 0; i--)
4118 if (!isspace((unsigned char) buf[i]))
4124 /* if no end found, we're done */
4129 * Otherwise we now look for the start. The start is either the last
4130 * character before any word-break character going backwards from the
4131 * end, or it's simply character 0. We also handle open quotes and
4134 for (start = end; start > 0; start--)
4136 if (buf[start] == '"')
4137 inquotes = !inquotes;
4140 if (buf[start] == ')')
4142 else if (buf[start] == '(')
4144 if (--parentheses <= 0)
4147 else if (parentheses == 0 &&
4148 strchr(WORD_BREAKS, buf[start - 1]))
4153 /* Return the word located at start to end inclusive */
4154 previous_words[words_found++] = outptr;
4155 i = end - start + 1;
4156 memcpy(outptr, &buf[start], i);
4160 /* Continue searching */
4164 /* Release parsing input workspace, if we made one above */
4165 if (buf != rl_line_buffer)
4168 *nwords = words_found;
4169 return previous_words;
4173 * Look up the type for the GUC variable with the passed name.
4175 * Returns NULL if the variable is unknown. Otherwise the returned string,
4176 * containing the type, has to be freed.
4179 get_guctype(const char *varname)
4181 PQExpBufferData query_buffer;
4184 char *guctype = NULL;
4186 e_varname = escape_string(varname);
4188 initPQExpBuffer(&query_buffer);
4189 appendPQExpBuffer(&query_buffer,
4190 "SELECT vartype FROM pg_catalog.pg_settings "
4191 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
4194 result = exec_query(query_buffer.data);
4195 termPQExpBuffer(&query_buffer);
4198 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
4199 guctype = pg_strdup(PQgetvalue(result, 0, 0));
4209 * Surround a string with single quotes. This works for both SQL and
4210 * psql internal. Currently disabled because it is reported not to
4211 * cooperate with certain versions of readline.
4214 quote_file_name(char *text, int match_type, char *quote_pointer)
4219 (void) quote_pointer; /* not used */
4221 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
4222 s = pg_malloc(length);
4224 strcpy(s + 1, text);
4225 if (match_type == SINGLE_MATCH)
4226 s[length - 2] = '\'';
4227 s[length - 1] = '\0';
4232 dequote_file_name(char *text, char quote_char)
4238 return pg_strdup(text);
4240 length = strlen(text);
4241 s = pg_malloc(length - 2 + 1);
4242 strlcpy(s, text +1, length - 2 + 1);
4246 #endif /* NOT_USED */
4248 #endif /* USE_READLINE */