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 "pqexpbuffer.h"
47 #include "stringutils.h"
49 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
50 #define filename_completion_function rl_filename_completion_function
52 /* missing in some header files */
53 extern char *filename_completion_function();
56 #ifdef HAVE_RL_COMPLETION_MATCHES
57 #define completion_matches rl_completion_matches
60 /* word break characters */
61 #define WORD_BREAKS "\t\n@$><=;|&{() "
64 * Since readline doesn't let us pass any state through to the tab completion
65 * callback, we have to use this global variable to let get_previous_words()
66 * get at the previous lines of the current command. Ick.
68 PQExpBuffer tab_completion_query_buf = NULL;
71 * This struct is used to define "schema queries", which are custom-built
72 * to obtain possibly-schema-qualified names of database objects. There is
73 * enough similarity in the structure that we don't want to repeat it each
74 * time. So we put the components of each query into this struct and
75 * assemble them with the common boilerplate in _complete_from_query().
77 typedef struct SchemaQuery
80 * Name of catalog or catalogs to be queried, with alias, eg.
81 * "pg_catalog.pg_class c". Note that "pg_namespace n" will be added.
86 * Selection condition --- only rows meeting this condition are candidates
87 * to display. If catname mentions multiple tables, include the necessary
88 * join condition here. For example, "c.relkind = 'r'". Write NULL (not
89 * an empty string) if not needed.
91 const char *selcondition;
94 * Visibility condition --- which rows are visible without schema
95 * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
97 const char *viscondition;
100 * Namespace --- name of field to join to pg_namespace.oid. For example,
103 const char *namespace;
106 * Result --- the appropriately-quoted name to return, in the case of an
107 * unqualified name. For example, "pg_catalog.quote_ident(c.relname)".
112 * In some cases a different result must be used for qualified names.
113 * Enter that here, or write NULL if result can be used.
115 const char *qualresult;
119 /* Store maximum number of records we want from database queries
120 * (implemented via SELECT ... LIMIT xx).
122 static int completion_max_records;
125 * Communication variables set by COMPLETE_WITH_FOO macros and then used by
126 * the completion callback functions. Ugly but there is no better way.
128 static const char *completion_charp; /* to pass a string */
129 static const char *const * completion_charpp; /* to pass a list of strings */
130 static const char *completion_info_charp; /* to pass a second string */
131 static const char *completion_info_charp2; /* to pass a third string */
132 static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
133 static bool completion_case_sensitive; /* completion is case sensitive */
136 * A few macros to ease typing. You can use these to complete the given
138 * 1) The results from a query you pass it. (Perhaps one of those below?)
139 * 2) The results from a schema query you pass it.
140 * 3) The items from a null-pointer-terminated list (with or without
141 * case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
142 * 4) A string constant.
143 * 5) The list of attributes of the given table (possibly schema-qualified).
144 * 6/ The list of arguments to the given function (possibly schema-qualified).
146 #define COMPLETE_WITH_QUERY(query) \
148 completion_charp = query; \
149 matches = completion_matches(text, complete_from_query); \
152 #define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
154 completion_squery = &(query); \
155 completion_charp = addon; \
156 matches = completion_matches(text, complete_from_schema_query); \
159 #define COMPLETE_WITH_LIST_CS(list) \
161 completion_charpp = list; \
162 completion_case_sensitive = true; \
163 matches = completion_matches(text, complete_from_list); \
166 #define COMPLETE_WITH_LIST(list) \
168 completion_charpp = list; \
169 completion_case_sensitive = false; \
170 matches = completion_matches(text, complete_from_list); \
173 #define COMPLETE_WITH_CONST(string) \
175 completion_charp = string; \
176 completion_case_sensitive = false; \
177 matches = completion_matches(text, complete_from_const); \
180 #define COMPLETE_WITH_ATTR(relation, addon) \
182 char *_completion_schema; \
183 char *_completion_table; \
185 _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
186 false, false, pset.encoding); \
187 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
188 false, false, pset.encoding); \
189 _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
190 false, false, pset.encoding); \
191 if (_completion_table == NULL) \
193 completion_charp = Query_for_list_of_attributes addon; \
194 completion_info_charp = relation; \
198 completion_charp = Query_for_list_of_attributes_with_schema addon; \
199 completion_info_charp = _completion_table; \
200 completion_info_charp2 = _completion_schema; \
202 matches = completion_matches(text, complete_from_query); \
205 #define COMPLETE_WITH_ENUM_VALUE(type) \
207 char *_completion_schema; \
208 char *_completion_type; \
210 _completion_schema = strtokx(type, " \t\n\r", ".", "\"", 0, \
211 false, false, pset.encoding); \
212 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
213 false, false, pset.encoding); \
214 _completion_type = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
215 false, false, pset.encoding); \
216 if (_completion_type == NULL)\
218 completion_charp = Query_for_list_of_enum_values; \
219 completion_info_charp = type; \
223 completion_charp = Query_for_list_of_enum_values_with_schema; \
224 completion_info_charp = _completion_type; \
225 completion_info_charp2 = _completion_schema; \
227 matches = completion_matches(text, complete_from_query); \
230 #define COMPLETE_WITH_FUNCTION_ARG(function) \
232 char *_completion_schema; \
233 char *_completion_function; \
235 _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
236 false, false, pset.encoding); \
237 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
238 false, false, pset.encoding); \
239 _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
240 false, false, pset.encoding); \
241 if (_completion_function == NULL) \
243 completion_charp = Query_for_list_of_arguments; \
244 completion_info_charp = function; \
248 completion_charp = Query_for_list_of_arguments_with_schema; \
249 completion_info_charp = _completion_function; \
250 completion_info_charp2 = _completion_schema; \
252 matches = completion_matches(text, complete_from_query); \
256 * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
257 * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
259 #define COMPLETE_WITH_LIST2(s1, s2) \
261 static const char *const list[] = { s1, s2, NULL }; \
262 COMPLETE_WITH_LIST(list); \
265 #define COMPLETE_WITH_LIST3(s1, s2, s3) \
267 static const char *const list[] = { s1, s2, s3, NULL }; \
268 COMPLETE_WITH_LIST(list); \
271 #define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
273 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
274 COMPLETE_WITH_LIST(list); \
277 #define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
279 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
280 COMPLETE_WITH_LIST(list); \
283 #define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \
285 static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \
286 COMPLETE_WITH_LIST(list); \
289 #define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \
291 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \
292 COMPLETE_WITH_LIST(list); \
295 #define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \
297 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \
298 COMPLETE_WITH_LIST(list); \
301 #define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
303 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
304 COMPLETE_WITH_LIST(list); \
307 #define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
309 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
310 COMPLETE_WITH_LIST(list); \
314 * Likewise for COMPLETE_WITH_LIST_CS.
316 #define COMPLETE_WITH_LIST_CS2(s1, s2) \
318 static const char *const list[] = { s1, s2, NULL }; \
319 COMPLETE_WITH_LIST_CS(list); \
322 #define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
324 static const char *const list[] = { s1, s2, s3, NULL }; \
325 COMPLETE_WITH_LIST_CS(list); \
328 #define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
330 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
331 COMPLETE_WITH_LIST_CS(list); \
334 #define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
336 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
337 COMPLETE_WITH_LIST_CS(list); \
341 * Assembly instructions for schema queries
344 static const SchemaQuery Query_for_list_of_aggregates = {
346 "pg_catalog.pg_proc p",
350 "pg_catalog.pg_function_is_visible(p.oid)",
354 "pg_catalog.quote_ident(p.proname)",
359 static const SchemaQuery Query_for_list_of_datatypes = {
361 "pg_catalog.pg_type t",
362 /* selcondition --- ignore table rowtypes and array types */
364 " OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
365 "AND t.typname !~ '^_'",
367 "pg_catalog.pg_type_is_visible(t.oid)",
371 "pg_catalog.format_type(t.oid, NULL)",
373 "pg_catalog.quote_ident(t.typname)"
376 static const SchemaQuery Query_for_list_of_domains = {
378 "pg_catalog.pg_type t",
382 "pg_catalog.pg_type_is_visible(t.oid)",
386 "pg_catalog.quote_ident(t.typname)",
391 static const SchemaQuery Query_for_list_of_functions = {
393 "pg_catalog.pg_proc p",
397 "pg_catalog.pg_function_is_visible(p.oid)",
401 "pg_catalog.quote_ident(p.proname)",
406 static const SchemaQuery Query_for_list_of_indexes = {
408 "pg_catalog.pg_class c",
410 "c.relkind IN ('i')",
412 "pg_catalog.pg_table_is_visible(c.oid)",
416 "pg_catalog.quote_ident(c.relname)",
421 static const SchemaQuery Query_for_list_of_sequences = {
423 "pg_catalog.pg_class c",
425 "c.relkind IN ('S')",
427 "pg_catalog.pg_table_is_visible(c.oid)",
431 "pg_catalog.quote_ident(c.relname)",
436 static const SchemaQuery Query_for_list_of_foreign_tables = {
438 "pg_catalog.pg_class c",
440 "c.relkind IN ('f')",
442 "pg_catalog.pg_table_is_visible(c.oid)",
446 "pg_catalog.quote_ident(c.relname)",
451 static const SchemaQuery Query_for_list_of_tables = {
453 "pg_catalog.pg_class c",
455 "c.relkind IN ('r', 'P')",
457 "pg_catalog.pg_table_is_visible(c.oid)",
461 "pg_catalog.quote_ident(c.relname)",
466 static const SchemaQuery Query_for_list_of_partitioned_tables = {
468 "pg_catalog.pg_class c",
470 "c.relkind IN ('P')",
472 "pg_catalog.pg_table_is_visible(c.oid)",
476 "pg_catalog.quote_ident(c.relname)",
481 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
483 "pg_catalog.pg_constraint c",
487 "true", /* there is no pg_constraint_is_visible */
491 "pg_catalog.quote_ident(c.conname)",
496 /* Relations supporting INSERT, UPDATE or DELETE */
497 static const SchemaQuery Query_for_list_of_updatables = {
499 "pg_catalog.pg_class c",
501 "c.relkind IN ('r', 'f', 'v', 'P')",
503 "pg_catalog.pg_table_is_visible(c.oid)",
507 "pg_catalog.quote_ident(c.relname)",
512 static const SchemaQuery Query_for_list_of_relations = {
514 "pg_catalog.pg_class c",
518 "pg_catalog.pg_table_is_visible(c.oid)",
522 "pg_catalog.quote_ident(c.relname)",
527 static const SchemaQuery Query_for_list_of_tsvmf = {
529 "pg_catalog.pg_class c",
531 "c.relkind IN ('r', 'S', 'v', 'm', 'f', 'P')",
533 "pg_catalog.pg_table_is_visible(c.oid)",
537 "pg_catalog.quote_ident(c.relname)",
542 static const SchemaQuery Query_for_list_of_tmf = {
544 "pg_catalog.pg_class c",
546 "c.relkind IN ('r', 'm', 'f')",
548 "pg_catalog.pg_table_is_visible(c.oid)",
552 "pg_catalog.quote_ident(c.relname)",
557 static const SchemaQuery Query_for_list_of_tm = {
559 "pg_catalog.pg_class c",
561 "c.relkind IN ('r', 'm')",
563 "pg_catalog.pg_table_is_visible(c.oid)",
567 "pg_catalog.quote_ident(c.relname)",
572 static const SchemaQuery Query_for_list_of_views = {
574 "pg_catalog.pg_class c",
576 "c.relkind IN ('v')",
578 "pg_catalog.pg_table_is_visible(c.oid)",
582 "pg_catalog.quote_ident(c.relname)",
587 static const SchemaQuery Query_for_list_of_matviews = {
589 "pg_catalog.pg_class c",
591 "c.relkind IN ('m')",
593 "pg_catalog.pg_table_is_visible(c.oid)",
597 "pg_catalog.quote_ident(c.relname)",
604 * Queries to get lists of names of various kinds of things, possibly
605 * restricted to names matching a partially entered name. In these queries,
606 * the first %s will be replaced by the text entered so far (suitably escaped
607 * to become a SQL literal string). %d will be replaced by the length of the
608 * string (in unescaped form). A second and third %s, if present, will be
609 * replaced by a suitably-escaped version of the string provided in
610 * completion_info_charp. A fourth and fifth %s are similarly replaced by
611 * completion_info_charp2.
613 * Beware that the allowed sequences of %s and %d are determined by
614 * _complete_from_query().
617 #define Query_for_list_of_attributes \
618 "SELECT pg_catalog.quote_ident(attname) "\
619 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
620 " WHERE c.oid = a.attrelid "\
621 " AND a.attnum > 0 "\
622 " AND NOT a.attisdropped "\
623 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
624 " AND (pg_catalog.quote_ident(relname)='%s' "\
625 " OR '\"' || relname || '\"'='%s') "\
626 " AND pg_catalog.pg_table_is_visible(c.oid)"
628 #define Query_for_list_of_attributes_with_schema \
629 "SELECT pg_catalog.quote_ident(attname) "\
630 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
631 " WHERE c.oid = a.attrelid "\
632 " AND n.oid = c.relnamespace "\
633 " AND a.attnum > 0 "\
634 " AND NOT a.attisdropped "\
635 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
636 " AND (pg_catalog.quote_ident(relname)='%s' "\
637 " OR '\"' || relname || '\"' ='%s') "\
638 " AND (pg_catalog.quote_ident(nspname)='%s' "\
639 " OR '\"' || nspname || '\"' ='%s') "
641 #define Query_for_list_of_enum_values \
642 "SELECT pg_catalog.quote_literal(enumlabel) "\
643 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t "\
644 " WHERE t.oid = e.enumtypid "\
645 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
646 " AND (pg_catalog.quote_ident(typname)='%s' "\
647 " OR '\"' || typname || '\"'='%s') "\
648 " AND pg_catalog.pg_type_is_visible(t.oid)"
650 #define Query_for_list_of_enum_values_with_schema \
651 "SELECT pg_catalog.quote_literal(enumlabel) "\
652 " FROM pg_catalog.pg_enum e, pg_catalog.pg_type t, pg_catalog.pg_namespace n "\
653 " WHERE t.oid = e.enumtypid "\
654 " AND n.oid = t.typnamespace "\
655 " AND substring(pg_catalog.quote_literal(enumlabel),1,%d)='%s' "\
656 " AND (pg_catalog.quote_ident(typname)='%s' "\
657 " OR '\"' || typname || '\"'='%s') "\
658 " AND (pg_catalog.quote_ident(nspname)='%s' "\
659 " OR '\"' || nspname || '\"' ='%s') "
661 #define Query_for_list_of_template_databases \
662 "SELECT pg_catalog.quote_ident(d.datname) "\
663 " FROM pg_catalog.pg_database d "\
664 " WHERE substring(pg_catalog.quote_ident(d.datname),1,%d)='%s' "\
665 " AND (d.datistemplate OR pg_catalog.pg_has_role(d.datdba, 'USAGE'))"
667 #define Query_for_list_of_databases \
668 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
669 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
671 #define Query_for_list_of_tablespaces \
672 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
673 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
675 #define Query_for_list_of_encodings \
676 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
677 " FROM pg_catalog.pg_conversion "\
678 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
680 #define Query_for_list_of_languages \
681 "SELECT pg_catalog.quote_ident(lanname) "\
682 " FROM pg_catalog.pg_language "\
683 " WHERE lanname != 'internal' "\
684 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
686 #define Query_for_list_of_schemas \
687 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
688 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
690 #define Query_for_list_of_alter_system_set_vars \
692 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
693 " WHERE context != 'internal' "\
694 " UNION ALL SELECT 'all') ss "\
695 " WHERE substring(name,1,%d)='%s'"
697 #define Query_for_list_of_set_vars \
699 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
700 " WHERE context IN ('user', 'superuser') "\
701 " UNION ALL SELECT 'constraints' "\
702 " UNION ALL SELECT 'transaction' "\
703 " UNION ALL SELECT 'session' "\
704 " UNION ALL SELECT 'role' "\
705 " UNION ALL SELECT 'tablespace' "\
706 " UNION ALL SELECT 'all') ss "\
707 " WHERE substring(name,1,%d)='%s'"
709 #define Query_for_list_of_show_vars \
711 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
712 " UNION ALL SELECT 'session authorization' "\
713 " UNION ALL SELECT 'all') ss "\
714 " WHERE substring(name,1,%d)='%s'"
716 #define Query_for_list_of_roles \
717 " SELECT pg_catalog.quote_ident(rolname) "\
718 " FROM pg_catalog.pg_roles "\
719 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
721 #define Query_for_list_of_grant_roles \
722 " SELECT pg_catalog.quote_ident(rolname) "\
723 " FROM pg_catalog.pg_roles "\
724 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
725 " UNION ALL SELECT 'PUBLIC'"\
726 " UNION ALL SELECT 'CURRENT_USER'"\
727 " UNION ALL SELECT 'SESSION_USER'"
729 /* the silly-looking length condition is just to eat up the current word */
730 #define Query_for_table_owning_index \
731 "SELECT pg_catalog.quote_ident(c1.relname) "\
732 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
733 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
734 " and (%d = pg_catalog.length('%s'))"\
735 " and pg_catalog.quote_ident(c2.relname)='%s'"\
736 " and pg_catalog.pg_table_is_visible(c2.oid)"
738 /* the silly-looking length condition is just to eat up the current word */
739 #define Query_for_index_of_table \
740 "SELECT pg_catalog.quote_ident(c2.relname) "\
741 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
742 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
743 " and (%d = pg_catalog.length('%s'))"\
744 " and pg_catalog.quote_ident(c1.relname)='%s'"\
745 " and pg_catalog.pg_table_is_visible(c2.oid)"
747 /* the silly-looking length condition is just to eat up the current word */
748 #define Query_for_constraint_of_table \
749 "SELECT pg_catalog.quote_ident(conname) "\
750 " FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
751 " WHERE c1.oid=conrelid and (%d = pg_catalog.length('%s'))"\
752 " and pg_catalog.quote_ident(c1.relname)='%s'"\
753 " and pg_catalog.pg_table_is_visible(c1.oid)"
755 #define Query_for_all_table_constraints \
756 "SELECT pg_catalog.quote_ident(conname) "\
757 " FROM pg_catalog.pg_constraint c "\
758 " WHERE c.conrelid <> 0 "
760 /* the silly-looking length condition is just to eat up the current word */
761 #define Query_for_constraint_of_type \
762 "SELECT pg_catalog.quote_ident(conname) "\
763 " FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
764 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
765 " and pg_catalog.quote_ident(t.typname)='%s'"\
766 " and pg_catalog.pg_type_is_visible(t.oid)"
768 /* the silly-looking length condition is just to eat up the current word */
769 #define Query_for_list_of_tables_for_constraint \
770 "SELECT pg_catalog.quote_ident(relname) "\
771 " FROM pg_catalog.pg_class"\
772 " WHERE (%d = pg_catalog.length('%s'))"\
774 " (SELECT conrelid FROM pg_catalog.pg_constraint "\
775 " WHERE pg_catalog.quote_ident(conname)='%s')"
777 /* the silly-looking length condition is just to eat up the current word */
778 #define Query_for_rule_of_table \
779 "SELECT pg_catalog.quote_ident(rulename) "\
780 " FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
781 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
782 " and pg_catalog.quote_ident(c1.relname)='%s'"\
783 " and pg_catalog.pg_table_is_visible(c1.oid)"
785 /* the silly-looking length condition is just to eat up the current word */
786 #define Query_for_list_of_tables_for_rule \
787 "SELECT pg_catalog.quote_ident(relname) "\
788 " FROM pg_catalog.pg_class"\
789 " WHERE (%d = pg_catalog.length('%s'))"\
791 " (SELECT ev_class FROM pg_catalog.pg_rewrite "\
792 " WHERE pg_catalog.quote_ident(rulename)='%s')"
794 /* the silly-looking length condition is just to eat up the current word */
795 #define Query_for_trigger_of_table \
796 "SELECT pg_catalog.quote_ident(tgname) "\
797 " FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
798 " WHERE c1.oid=tgrelid 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)"\
801 " and not tgisinternal"
803 /* the silly-looking length condition is just to eat up the current word */
804 #define Query_for_list_of_tables_for_trigger \
805 "SELECT pg_catalog.quote_ident(relname) "\
806 " FROM pg_catalog.pg_class"\
807 " WHERE (%d = pg_catalog.length('%s'))"\
809 " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
810 " WHERE pg_catalog.quote_ident(tgname)='%s')"
812 #define Query_for_list_of_ts_configurations \
813 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
814 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
816 #define Query_for_list_of_ts_dictionaries \
817 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
818 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
820 #define Query_for_list_of_ts_parsers \
821 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
822 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
824 #define Query_for_list_of_ts_templates \
825 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
826 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
828 #define Query_for_list_of_fdws \
829 " SELECT pg_catalog.quote_ident(fdwname) "\
830 " FROM pg_catalog.pg_foreign_data_wrapper "\
831 " WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
833 #define Query_for_list_of_servers \
834 " SELECT pg_catalog.quote_ident(srvname) "\
835 " FROM pg_catalog.pg_foreign_server "\
836 " WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
838 #define Query_for_list_of_user_mappings \
839 " SELECT pg_catalog.quote_ident(usename) "\
840 " FROM pg_catalog.pg_user_mappings "\
841 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
843 #define Query_for_list_of_access_methods \
844 " SELECT pg_catalog.quote_ident(amname) "\
845 " FROM pg_catalog.pg_am "\
846 " WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
848 #define Query_for_list_of_publications \
849 " SELECT pg_catalog.quote_ident(pubname) "\
850 " FROM pg_catalog.pg_publication "\
851 " WHERE substring(pg_catalog.quote_ident(pubname),1,%d)='%s'"
853 #define Query_for_list_of_subscriptions \
854 " SELECT pg_catalog.quote_ident(s.subname) "\
855 " FROM pg_catalog.pg_subscription s, pg_catalog.pg_database d "\
856 " WHERE substring(pg_catalog.quote_ident(s.subname),1,%d)='%s' "\
857 " AND d.datname = pg_catalog.current_database() "\
858 " AND s.subdbid = d.oid"
860 /* the silly-looking length condition is just to eat up the current word */
861 #define Query_for_list_of_arguments \
862 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
863 " FROM pg_catalog.pg_proc "\
864 " WHERE (%d = pg_catalog.length('%s'))"\
865 " AND (pg_catalog.quote_ident(proname)='%s'"\
866 " OR '\"' || proname || '\"'='%s') "\
867 " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
869 /* the silly-looking length condition is just to eat up the current word */
870 #define Query_for_list_of_arguments_with_schema \
871 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
872 " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
873 " WHERE (%d = pg_catalog.length('%s'))"\
874 " AND n.oid = p.pronamespace "\
875 " AND (pg_catalog.quote_ident(proname)='%s' "\
876 " OR '\"' || proname || '\"' ='%s') "\
877 " AND (pg_catalog.quote_ident(nspname)='%s' "\
878 " OR '\"' || nspname || '\"' ='%s') "
880 #define Query_for_list_of_extensions \
881 " SELECT pg_catalog.quote_ident(extname) "\
882 " FROM pg_catalog.pg_extension "\
883 " WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
885 #define Query_for_list_of_available_extensions \
886 " SELECT pg_catalog.quote_ident(name) "\
887 " FROM pg_catalog.pg_available_extensions "\
888 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
890 /* the silly-looking length condition is just to eat up the current word */
891 #define Query_for_list_of_available_extension_versions \
892 " SELECT pg_catalog.quote_ident(version) "\
893 " FROM pg_catalog.pg_available_extension_versions "\
894 " WHERE (%d = pg_catalog.length('%s'))"\
895 " AND pg_catalog.quote_ident(name)='%s'"
897 /* the silly-looking length condition is just to eat up the current word */
898 #define Query_for_list_of_available_extension_versions_with_TO \
899 " SELECT 'TO ' || pg_catalog.quote_ident(version) "\
900 " FROM pg_catalog.pg_available_extension_versions "\
901 " WHERE (%d = pg_catalog.length('%s'))"\
902 " AND pg_catalog.quote_ident(name)='%s'"
904 #define Query_for_list_of_prepared_statements \
905 " SELECT pg_catalog.quote_ident(name) "\
906 " FROM pg_catalog.pg_prepared_statements "\
907 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
909 #define Query_for_list_of_event_triggers \
910 " SELECT pg_catalog.quote_ident(evtname) "\
911 " FROM pg_catalog.pg_event_trigger "\
912 " WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
914 #define Query_for_list_of_tablesample_methods \
915 " SELECT pg_catalog.quote_ident(proname) "\
916 " FROM pg_catalog.pg_proc "\
917 " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
918 " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
919 " substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
921 #define Query_for_list_of_policies \
922 " SELECT pg_catalog.quote_ident(polname) "\
923 " FROM pg_catalog.pg_policy "\
924 " WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
926 #define Query_for_list_of_tables_for_policy \
927 "SELECT pg_catalog.quote_ident(relname) "\
928 " FROM pg_catalog.pg_class"\
929 " WHERE (%d = pg_catalog.length('%s'))"\
931 " (SELECT polrelid FROM pg_catalog.pg_policy "\
932 " WHERE pg_catalog.quote_ident(polname)='%s')"
934 #define Query_for_enum \
935 " SELECT name FROM ( "\
936 " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
937 " FROM pg_catalog.pg_settings "\
938 " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
940 " SELECT 'DEFAULT' ) ss "\
941 " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
943 /* the silly-looking length condition is just to eat up the current word */
944 #define Query_for_partition_of_table \
945 "SELECT pg_catalog.quote_ident(c2.relname) "\
946 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_inherits i"\
947 " WHERE c1.oid=i.inhparent and i.inhrelid=c2.oid"\
948 " and (%d = pg_catalog.length('%s'))"\
949 " and pg_catalog.quote_ident(c1.relname)='%s'"\
950 " and pg_catalog.pg_table_is_visible(c2.oid)"\
951 " and c2.relispartition = 'true'"
954 * This is a list of all "things" in Pgsql, which can show up after CREATE or
955 * DROP; and there is also a query to get a list of them.
961 const char *query; /* simple query, or NULL */
962 const SchemaQuery *squery; /* schema query, or NULL */
963 const bits32 flags; /* visibility flags, see below */
966 #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
967 #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
968 #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP)
970 static const pgsql_thing_t words_after_create[] = {
971 {"ACCESS METHOD", NULL, NULL},
972 {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
973 {"CAST", NULL, NULL}, /* Casts have complex structures for names, so
975 {"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'"},
978 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
979 * to be used only by pg_dump.
981 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
982 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
983 {"DATABASE", Query_for_list_of_databases},
984 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
985 {"DOMAIN", NULL, &Query_for_list_of_domains},
986 {"EVENT TRIGGER", NULL, NULL},
987 {"EXTENSION", Query_for_list_of_extensions},
988 {"FOREIGN DATA WRAPPER", NULL, NULL},
989 {"FOREIGN TABLE", NULL, NULL},
990 {"FUNCTION", NULL, &Query_for_list_of_functions},
991 {"GROUP", Query_for_list_of_roles},
992 {"LANGUAGE", Query_for_list_of_languages},
993 {"INDEX", NULL, &Query_for_list_of_indexes},
994 {"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
995 {"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a
997 {"OWNED", NULL, NULL, THING_NO_CREATE}, /* for DROP OWNED BY ... */
998 {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
999 {"POLICY", NULL, NULL},
1000 {"PUBLICATION", Query_for_list_of_publications},
1001 {"ROLE", Query_for_list_of_roles},
1002 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
1003 {"SCHEMA", Query_for_list_of_schemas},
1004 {"SEQUENCE", NULL, &Query_for_list_of_sequences},
1005 {"SERVER", Query_for_list_of_servers},
1006 {"SUBSCRIPTION", Query_for_list_of_subscriptions},
1007 {"TABLE", NULL, &Query_for_list_of_tables},
1008 {"TABLESPACE", Query_for_list_of_tablespaces},
1009 {"TEMP", NULL, NULL, THING_NO_DROP}, /* for CREATE TEMP TABLE ... */
1010 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
1011 {"TEXT SEARCH", NULL, NULL},
1012 {"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"},
1013 {"TYPE", NULL, &Query_for_list_of_datatypes},
1014 {"UNIQUE", NULL, NULL, THING_NO_DROP}, /* for CREATE UNIQUE INDEX ... */
1015 {"UNLOGGED", NULL, NULL, THING_NO_DROP}, /* for CREATE UNLOGGED TABLE
1017 {"USER", Query_for_list_of_roles},
1018 {"USER MAPPING FOR", NULL, NULL},
1019 {"VIEW", NULL, &Query_for_list_of_views},
1020 {NULL} /* end of list */
1024 /* Forward declaration of functions */
1025 static char **psql_completion(const char *text, int start, int end);
1026 static char *create_command_generator(const char *text, int state);
1027 static char *drop_command_generator(const char *text, int state);
1028 static char *complete_from_query(const char *text, int state);
1029 static char *complete_from_schema_query(const char *text, int state);
1030 static char *_complete_from_query(int is_schema_query,
1031 const char *text, int state);
1032 static char *complete_from_list(const char *text, int state);
1033 static char *complete_from_const(const char *text, int state);
1034 static void append_variable_names(char ***varnames, int *nvars,
1035 int *maxvars, const char *varname,
1036 const char *prefix, const char *suffix);
1037 static char **complete_from_variables(const char *text,
1038 const char *prefix, const char *suffix, bool need_value);
1039 static char *complete_from_files(const char *text, int state);
1041 static char *pg_strdup_keyword_case(const char *s, const char *ref);
1042 static char *escape_string(const char *text);
1043 static PGresult *exec_query(const char *query);
1045 static char **get_previous_words(int point, char **buffer, int *nwords);
1047 static char *get_guctype(const char *varname);
1050 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
1051 static char *dequote_file_name(char *text, char quote_char);
1056 * Initialize the readline library for our purposes.
1059 initialize_readline(void)
1061 rl_readline_name = (char *) pset.progname;
1062 rl_attempted_completion_function = psql_completion;
1064 rl_basic_word_break_characters = WORD_BREAKS;
1066 completion_max_records = 1000;
1069 * There is a variable rl_completion_query_items for this but apparently
1070 * it's not defined everywhere.
1075 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
1076 * using case-insensitive or case-sensitive comparisons.
1078 * If pattern is NULL, it's a wild card that matches any word.
1079 * If pattern begins with '!', the result is negated, ie we check that 'word'
1080 * does *not* match any alternative appearing in the rest of 'pattern'.
1081 * Any alternative can end with '*' which is a wild card, i.e., it means
1082 * match any word that matches the characters so far. (We do not currently
1083 * support '*' elsewhere than the end of an alternative.)
1085 * For readability, callers should use the macros MatchAny and MatchAnyExcept
1086 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
1087 * just be written directly in patterns.)
1089 #define MatchAny NULL
1090 #define MatchAnyExcept(pattern) ("!" pattern)
1093 word_matches_internal(const char *pattern,
1095 bool case_sensitive)
1100 /* NULL pattern matches anything. */
1101 if (pattern == NULL)
1104 /* Handle negated patterns from the MatchAnyExcept macro. */
1105 if (*pattern == '!')
1106 return !word_matches_internal(pattern + 1, word, case_sensitive);
1108 /* Else consider each alternative in the pattern. */
1109 wordlen = strlen(word);
1114 /* Find end of current alternative. */
1116 while (*c != '\0' && *c != '|')
1118 /* Was there a wild card? (Assumes first alternative is not empty) */
1121 /* Yes, wildcard match? */
1122 patternlen = c - pattern - 1;
1123 if (wordlen >= patternlen &&
1125 strncmp(word, pattern, patternlen) == 0 :
1126 pg_strncasecmp(word, pattern, patternlen) == 0))
1131 /* No, plain match? */
1132 patternlen = c - pattern;
1133 if (wordlen == patternlen &&
1135 strncmp(word, pattern, wordlen) == 0 :
1136 pg_strncasecmp(word, pattern, wordlen) == 0))
1139 /* Out of alternatives? */
1142 /* Nope, try next alternative. */
1150 * There are enough matching calls below that it seems worth having these two
1151 * interface routines rather than including a third parameter in every call.
1153 * word_matches --- match case-insensitively.
1156 word_matches(const char *pattern, const char *word)
1158 return word_matches_internal(pattern, word, false);
1162 * word_matches_cs --- match case-sensitively.
1165 word_matches_cs(const char *pattern, const char *word)
1167 return word_matches_internal(pattern, word, true);
1171 * Check if the final character of 's' is 'c'.
1174 ends_with(const char *s, char c)
1176 size_t length = strlen(s);
1178 return (length > 0 && s[length - 1] == c);
1182 * The completion function.
1184 * According to readline spec this gets passed the text entered so far and its
1185 * start and end positions in the readline buffer. The return value is some
1186 * partially obscure list format that can be generated by readline's
1187 * completion_matches() function, so we don't have to worry about it.
1190 psql_completion(const char *text, int start, int end)
1192 /* This is the variable we'll return. */
1193 char **matches = NULL;
1195 /* Workspace for parsed words. */
1198 /* This array will contain pointers to parsed words. */
1199 char **previous_words;
1201 /* The number of words found on the input line. */
1202 int previous_words_count;
1205 * For compactness, we use these macros to reference previous_words[].
1206 * Caution: do not access a previous_words[] entry without having checked
1207 * previous_words_count to be sure it's valid. In most cases below, that
1208 * check is implicit in a TailMatches() or similar macro, but in some
1209 * places we have to check it explicitly.
1211 #define prev_wd (previous_words[0])
1212 #define prev2_wd (previous_words[1])
1213 #define prev3_wd (previous_words[2])
1214 #define prev4_wd (previous_words[3])
1215 #define prev5_wd (previous_words[4])
1216 #define prev6_wd (previous_words[5])
1217 #define prev7_wd (previous_words[6])
1218 #define prev8_wd (previous_words[7])
1219 #define prev9_wd (previous_words[8])
1221 /* Macros for matching the last N words before point, case-insensitively. */
1222 #define TailMatches1(p1) \
1223 (previous_words_count >= 1 && \
1224 word_matches(p1, prev_wd))
1226 #define TailMatches2(p2, p1) \
1227 (previous_words_count >= 2 && \
1228 word_matches(p1, prev_wd) && \
1229 word_matches(p2, prev2_wd))
1231 #define TailMatches3(p3, p2, p1) \
1232 (previous_words_count >= 3 && \
1233 word_matches(p1, prev_wd) && \
1234 word_matches(p2, prev2_wd) && \
1235 word_matches(p3, prev3_wd))
1237 #define TailMatches4(p4, p3, p2, p1) \
1238 (previous_words_count >= 4 && \
1239 word_matches(p1, prev_wd) && \
1240 word_matches(p2, prev2_wd) && \
1241 word_matches(p3, prev3_wd) && \
1242 word_matches(p4, prev4_wd))
1244 #define TailMatches5(p5, p4, p3, p2, p1) \
1245 (previous_words_count >= 5 && \
1246 word_matches(p1, prev_wd) && \
1247 word_matches(p2, prev2_wd) && \
1248 word_matches(p3, prev3_wd) && \
1249 word_matches(p4, prev4_wd) && \
1250 word_matches(p5, prev5_wd))
1252 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1253 (previous_words_count >= 6 && \
1254 word_matches(p1, prev_wd) && \
1255 word_matches(p2, prev2_wd) && \
1256 word_matches(p3, prev3_wd) && \
1257 word_matches(p4, prev4_wd) && \
1258 word_matches(p5, prev5_wd) && \
1259 word_matches(p6, prev6_wd))
1261 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1262 (previous_words_count >= 7 && \
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) && \
1268 word_matches(p6, prev6_wd) && \
1269 word_matches(p7, prev7_wd))
1271 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1272 (previous_words_count >= 8 && \
1273 word_matches(p1, prev_wd) && \
1274 word_matches(p2, prev2_wd) && \
1275 word_matches(p3, prev3_wd) && \
1276 word_matches(p4, prev4_wd) && \
1277 word_matches(p5, prev5_wd) && \
1278 word_matches(p6, prev6_wd) && \
1279 word_matches(p7, prev7_wd) && \
1280 word_matches(p8, prev8_wd))
1282 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1283 (previous_words_count >= 9 && \
1284 word_matches(p1, prev_wd) && \
1285 word_matches(p2, prev2_wd) && \
1286 word_matches(p3, prev3_wd) && \
1287 word_matches(p4, prev4_wd) && \
1288 word_matches(p5, prev5_wd) && \
1289 word_matches(p6, prev6_wd) && \
1290 word_matches(p7, prev7_wd) && \
1291 word_matches(p8, prev8_wd) && \
1292 word_matches(p9, prev9_wd))
1294 /* Macros for matching the last N words before point, case-sensitively. */
1295 #define TailMatchesCS1(p1) \
1296 (previous_words_count >= 1 && \
1297 word_matches_cs(p1, prev_wd))
1298 #define TailMatchesCS2(p2, p1) \
1299 (previous_words_count >= 2 && \
1300 word_matches_cs(p1, prev_wd) && \
1301 word_matches_cs(p2, prev2_wd))
1304 * Macros for matching N words beginning at the start of the line,
1305 * case-insensitively.
1307 #define Matches1(p1) \
1308 (previous_words_count == 1 && \
1310 #define Matches2(p1, p2) \
1311 (previous_words_count == 2 && \
1312 TailMatches2(p1, p2))
1313 #define Matches3(p1, p2, p3) \
1314 (previous_words_count == 3 && \
1315 TailMatches3(p1, p2, p3))
1316 #define Matches4(p1, p2, p3, p4) \
1317 (previous_words_count == 4 && \
1318 TailMatches4(p1, p2, p3, p4))
1319 #define Matches5(p1, p2, p3, p4, p5) \
1320 (previous_words_count == 5 && \
1321 TailMatches5(p1, p2, p3, p4, p5))
1322 #define Matches6(p1, p2, p3, p4, p5, p6) \
1323 (previous_words_count == 6 && \
1324 TailMatches6(p1, p2, p3, p4, p5, p6))
1325 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1326 (previous_words_count == 7 && \
1327 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1328 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1329 (previous_words_count == 8 && \
1330 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1331 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1332 (previous_words_count == 9 && \
1333 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1336 * Macros for matching N words at the start of the line, regardless of
1337 * what is after them, case-insensitively.
1339 #define HeadMatches1(p1) \
1340 (previous_words_count >= 1 && \
1341 word_matches(p1, previous_words[previous_words_count - 1]))
1343 #define HeadMatches2(p1, p2) \
1344 (previous_words_count >= 2 && \
1345 word_matches(p1, previous_words[previous_words_count - 1]) && \
1346 word_matches(p2, previous_words[previous_words_count - 2]))
1348 #define HeadMatches3(p1, p2, p3) \
1349 (previous_words_count >= 3 && \
1350 word_matches(p1, previous_words[previous_words_count - 1]) && \
1351 word_matches(p2, previous_words[previous_words_count - 2]) && \
1352 word_matches(p3, previous_words[previous_words_count - 3]))
1354 /* Known command-starting keywords. */
1355 static const char *const sql_commands[] = {
1356 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
1357 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1358 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1359 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1360 "MOVE", "NOTIFY", "PREPARE",
1361 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1362 "RESET", "REVOKE", "ROLLBACK",
1363 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1364 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1368 /* psql's backslash commands. */
1369 static const char *const backslash_commands[] = {
1370 "\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy",
1371 "\\copyright", "\\crosstabview",
1372 "\\d", "\\da", "\\dA", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1373 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1374 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1375 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
1376 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1377 "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
1378 "\\f", "\\g", "\\gexec", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
1379 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1380 "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
1381 "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t", "\\T",
1382 "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL
1385 (void) end; /* "end" is not used */
1387 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1388 rl_completion_append_character = ' ';
1391 /* Clear a few things. */
1392 completion_charp = NULL;
1393 completion_charpp = NULL;
1394 completion_info_charp = NULL;
1395 completion_info_charp2 = NULL;
1398 * Scan the input line to extract the words before our current position.
1399 * According to those we'll make some smart decisions on what the user is
1400 * probably intending to type.
1402 previous_words = get_previous_words(start,
1404 &previous_words_count);
1406 /* If current word is a backslash command, offer completions for that */
1407 if (text[0] == '\\')
1408 COMPLETE_WITH_LIST_CS(backslash_commands);
1410 /* If current word is a variable interpolation, handle that case */
1411 else if (text[0] == ':' && text[1] != ':')
1413 if (text[1] == '\'')
1414 matches = complete_from_variables(text, ":'", "'", true);
1415 else if (text[1] == '"')
1416 matches = complete_from_variables(text, ":\"", "\"", true);
1418 matches = complete_from_variables(text, ":", "", true);
1421 /* If no previous word, suggest one of the basic sql commands */
1422 else if (previous_words_count == 0)
1423 COMPLETE_WITH_LIST(sql_commands);
1426 /* complete with something you can create */
1427 else if (TailMatches1("CREATE"))
1428 matches = completion_matches(text, create_command_generator);
1430 /* DROP, but not DROP embedded in other commands */
1431 /* complete with something you can drop */
1432 else if (Matches1("DROP"))
1433 matches = completion_matches(text, drop_command_generator);
1438 else if (Matches2("ALTER", "TABLE"))
1439 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1440 "UNION SELECT 'ALL IN TABLESPACE'");
1442 /* ALTER something */
1443 else if (Matches1("ALTER"))
1445 static const char *const list_ALTER[] =
1446 {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
1447 "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
1448 "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR",
1449 "POLICY", "PUBLICATION", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE",
1450 "SUBSCRIPTION", "SYSTEM", "TABLE", "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
1451 "USER", "USER MAPPING FOR", "VIEW", NULL};
1453 COMPLETE_WITH_LIST(list_ALTER);
1455 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1456 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1457 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1458 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1459 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1460 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1461 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1462 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1463 COMPLETE_WITH_CONST("SET TABLESPACE");
1464 /* ALTER AGGREGATE,FUNCTION <name> */
1465 else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1466 COMPLETE_WITH_CONST("(");
1467 /* ALTER AGGREGATE,FUNCTION <name> (...) */
1468 else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1470 if (ends_with(prev_wd, ')'))
1471 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1473 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1475 /* ALTER PUBLICATION <name> ...*/
1476 else if (Matches3("ALTER","PUBLICATION",MatchAny))
1478 COMPLETE_WITH_LIST6("WITH", "ADD TABLE", "SET TABLE", "DROP TABLE",
1479 "OWNER TO", "RENAME TO");
1481 /* ALTER PUBLICATION <name> .. WITH ( ... */
1482 else if (HeadMatches3("ALTER", "PUBLICATION",MatchAny) && TailMatches2("WITH", "("))
1484 COMPLETE_WITH_LIST6("PUBLISH INSERT", "NOPUBLISH INSERT", "PUBLISH UPDATE",
1485 "NOPUBLISH UPDATE", "PUBLISH DELETE", "NOPUBLISH DELETE");
1487 /* ALTER SUBSCRIPTION <name> ... */
1488 else if (Matches3("ALTER","SUBSCRIPTION",MatchAny))
1490 COMPLETE_WITH_LIST7("WITH", "CONNECTION", "SET PUBLICATION", "ENABLE",
1491 "DISABLE", "OWNER TO", "RENAME TO");
1493 else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("WITH", "("))
1495 COMPLETE_WITH_CONST("SLOT NAME");
1497 /* ALTER SCHEMA <name> */
1498 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1499 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1501 /* ALTER COLLATION <name> */
1502 else if (Matches3("ALTER", "COLLATION", MatchAny))
1503 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1505 /* ALTER CONVERSION <name> */
1506 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1507 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1509 /* ALTER DATABASE <name> */
1510 else if (Matches3("ALTER", "DATABASE", MatchAny))
1511 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1512 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1513 "CONNECTION LIMIT");
1515 /* ALTER EVENT TRIGGER */
1516 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1517 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1519 /* ALTER EVENT TRIGGER <name> */
1520 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1521 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1523 /* ALTER EVENT TRIGGER <name> ENABLE */
1524 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1525 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1527 /* ALTER EXTENSION <name> */
1528 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1529 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1531 /* ALTER EXTENSION <name> UPDATE */
1532 else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
1534 completion_info_charp = prev2_wd;
1535 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
1538 /* ALTER EXTENSION <name> UPDATE TO */
1539 else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
1541 completion_info_charp = prev3_wd;
1542 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
1546 else if (Matches2("ALTER", "FOREIGN"))
1547 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1549 /* ALTER FOREIGN DATA WRAPPER <name> */
1550 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1551 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1553 /* ALTER FOREIGN TABLE <name> */
1554 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1556 static const char *const list_ALTER_FOREIGN_TABLE[] =
1557 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1558 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1559 "VALIDATE CONSTRAINT", NULL};
1561 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1565 else if (Matches2("ALTER", "INDEX"))
1566 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1567 "UNION SELECT 'ALL IN TABLESPACE'");
1568 /* ALTER INDEX <name> */
1569 else if (Matches3("ALTER", "INDEX", MatchAny))
1570 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1571 /* ALTER INDEX <name> SET */
1572 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1573 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1574 /* ALTER INDEX <name> RESET */
1575 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1576 COMPLETE_WITH_CONST("(");
1577 /* ALTER INDEX <foo> SET|RESET ( */
1578 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1579 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1580 "gin_pending_list_limit");
1581 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1582 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1583 "gin_pending_list_limit =");
1585 /* ALTER LANGUAGE <name> */
1586 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1587 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1589 /* ALTER LARGE OBJECT <oid> */
1590 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1591 COMPLETE_WITH_CONST("OWNER TO");
1593 /* ALTER MATERIALIZED VIEW */
1594 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1595 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1596 "UNION SELECT 'ALL IN TABLESPACE'");
1598 /* ALTER USER,ROLE <name> */
1599 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1600 !TailMatches2("USER", "MAPPING"))
1602 static const char *const list_ALTERUSER[] =
1603 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1604 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1605 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1606 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1607 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1608 "VALID UNTIL", "WITH", NULL};
1610 COMPLETE_WITH_LIST(list_ALTERUSER);
1613 /* ALTER USER,ROLE <name> WITH */
1614 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1616 /* Similar to the above, but don't complete "WITH" again. */
1617 static const char *const list_ALTERUSER_WITH[] =
1618 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1619 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1620 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1621 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1622 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1623 "VALID UNTIL", NULL};
1625 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1628 /* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
1629 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
1630 COMPLETE_WITH_CONST("PASSWORD");
1631 /* ALTER DEFAULT PRIVILEGES */
1632 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1633 COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
1634 /* ALTER DEFAULT PRIVILEGES FOR */
1635 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1636 COMPLETE_WITH_CONST("ROLE");
1637 /* ALTER DEFAULT PRIVILEGES IN */
1638 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "IN"))
1639 COMPLETE_WITH_CONST("SCHEMA");
1640 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... */
1641 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1643 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "IN SCHEMA");
1644 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... */
1645 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1647 COMPLETE_WITH_LIST3("GRANT", "REVOKE", "FOR ROLE");
1648 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR */
1649 else if (Matches7("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1651 COMPLETE_WITH_CONST("ROLE");
1652 /* ALTER DEFAULT PRIVILEGES FOR ROLE|USER ... IN SCHEMA ... */
1653 /* ALTER DEFAULT PRIVILEGES IN SCHEMA ... FOR ROLE|USER ... */
1654 else if (Matches9("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER",
1655 MatchAny, "IN", "SCHEMA", MatchAny) ||
1656 Matches9("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA",
1657 MatchAny, "FOR", "ROLE|USER", MatchAny))
1658 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1659 /* ALTER DOMAIN <name> */
1660 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1661 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1662 "VALIDATE CONSTRAINT");
1663 /* ALTER DOMAIN <sth> DROP */
1664 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1665 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1666 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1667 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1669 completion_info_charp = prev3_wd;
1670 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1672 /* ALTER DOMAIN <sth> RENAME */
1673 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1674 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1675 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1676 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1677 COMPLETE_WITH_CONST("TO");
1679 /* ALTER DOMAIN <sth> SET */
1680 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1681 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1682 /* ALTER SEQUENCE <name> */
1683 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1685 static const char *const list_ALTERSEQUENCE[] =
1686 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1687 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1689 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1691 /* ALTER SEQUENCE <name> NO */
1692 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1693 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1694 /* ALTER SERVER <name> */
1695 else if (Matches3("ALTER", "SERVER", MatchAny))
1696 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1697 /* ALTER SERVER <name> VERSION <version> */
1698 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1699 COMPLETE_WITH_CONST("OPTIONS");
1700 /* ALTER SYSTEM SET, RESET, RESET ALL */
1701 else if (Matches2("ALTER", "SYSTEM"))
1702 COMPLETE_WITH_LIST2("SET", "RESET");
1703 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1704 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1705 else if (Matches4("ALTER", "SYSTEM", "SET", MatchAny))
1706 COMPLETE_WITH_CONST("TO");
1707 /* ALTER VIEW <name> */
1708 else if (Matches3("ALTER", "VIEW", MatchAny))
1709 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1711 /* ALTER MATERIALIZED VIEW <name> */
1712 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1713 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1716 /* ALTER POLICY <name> */
1717 else if (Matches2("ALTER", "POLICY"))
1718 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1719 /* ALTER POLICY <name> ON */
1720 else if (Matches3("ALTER", "POLICY", MatchAny))
1721 COMPLETE_WITH_CONST("ON");
1722 /* ALTER POLICY <name> ON <table> */
1723 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1725 completion_info_charp = prev2_wd;
1726 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1728 /* ALTER POLICY <name> ON <table> - show options */
1729 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1730 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1731 /* ALTER POLICY <name> ON <table> TO <role> */
1732 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1733 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1734 /* ALTER POLICY <name> ON <table> USING ( */
1735 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1736 COMPLETE_WITH_CONST("(");
1737 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1738 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1739 COMPLETE_WITH_CONST("(");
1741 /* ALTER RULE <name>, add ON */
1742 else if (Matches3("ALTER", "RULE", MatchAny))
1743 COMPLETE_WITH_CONST("ON");
1745 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1746 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1748 completion_info_charp = prev2_wd;
1749 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1752 /* ALTER RULE <name> ON <name> */
1753 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1754 COMPLETE_WITH_CONST("RENAME TO");
1756 /* ALTER TRIGGER <name>, add ON */
1757 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1758 COMPLETE_WITH_CONST("ON");
1760 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1762 completion_info_charp = prev2_wd;
1763 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1767 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1769 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1770 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1772 /* ALTER TRIGGER <name> ON <name> */
1773 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1774 COMPLETE_WITH_CONST("RENAME TO");
1777 * If we detect ALTER TABLE <name>, suggest sub commands
1779 else if (Matches3("ALTER", "TABLE", MatchAny))
1781 static const char *const list_ALTER2[] =
1782 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1783 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1784 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", "ATTACH PARTITION",
1785 "DETACH PARTITION", NULL};
1787 COMPLETE_WITH_LIST(list_ALTER2);
1789 /* ALTER TABLE xxx ENABLE */
1790 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1791 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1793 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1794 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1795 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1797 completion_info_charp = prev3_wd;
1798 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1800 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1802 completion_info_charp = prev4_wd;
1803 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1805 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1807 completion_info_charp = prev3_wd;
1808 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1810 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1812 completion_info_charp = prev4_wd;
1813 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1815 /* ALTER TABLE xxx INHERIT */
1816 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1817 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1818 /* ALTER TABLE xxx NO INHERIT */
1819 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1820 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1821 /* ALTER TABLE xxx DISABLE */
1822 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1823 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1824 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1826 completion_info_charp = prev3_wd;
1827 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1829 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1831 completion_info_charp = prev3_wd;
1832 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1835 /* ALTER TABLE xxx ALTER */
1836 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1837 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1839 /* ALTER TABLE xxx RENAME */
1840 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1841 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1842 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1843 COMPLETE_WITH_ATTR(prev3_wd, "");
1845 /* ALTER TABLE xxx RENAME yyy */
1846 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1847 COMPLETE_WITH_CONST("TO");
1849 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1850 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1851 COMPLETE_WITH_CONST("TO");
1853 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1854 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1855 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1856 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1857 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1858 COMPLETE_WITH_ATTR(prev3_wd, "");
1861 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1862 * provide list of constraints
1864 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1866 completion_info_charp = prev3_wd;
1867 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1869 /* ALTER TABLE ALTER [COLUMN] <foo> */
1870 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1871 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1872 COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
1873 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1874 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1875 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1876 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1877 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1878 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1879 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1880 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1881 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1882 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1883 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1884 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1885 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1886 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1887 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1888 COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
1889 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1890 COMPLETE_WITH_CONST("ON");
1891 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1893 completion_info_charp = prev3_wd;
1894 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1896 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1897 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1898 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1902 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1905 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1906 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1907 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
1908 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
1909 COMPLETE_WITH_CONST("OIDS");
1910 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1911 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1912 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
1913 /* ALTER TABLE <foo> RESET */
1914 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
1915 COMPLETE_WITH_CONST("(");
1916 /* ALTER TABLE <foo> SET|RESET ( */
1917 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1919 static const char *const list_TABLEOPTIONS[] =
1921 "autovacuum_analyze_scale_factor",
1922 "autovacuum_analyze_threshold",
1923 "autovacuum_enabled",
1924 "autovacuum_freeze_max_age",
1925 "autovacuum_freeze_min_age",
1926 "autovacuum_freeze_table_age",
1927 "autovacuum_multixact_freeze_max_age",
1928 "autovacuum_multixact_freeze_min_age",
1929 "autovacuum_multixact_freeze_table_age",
1930 "autovacuum_vacuum_cost_delay",
1931 "autovacuum_vacuum_cost_limit",
1932 "autovacuum_vacuum_scale_factor",
1933 "autovacuum_vacuum_threshold",
1936 "log_autovacuum_min_duration",
1937 "toast.autovacuum_enabled",
1938 "toast.autovacuum_freeze_max_age",
1939 "toast.autovacuum_freeze_min_age",
1940 "toast.autovacuum_freeze_table_age",
1941 "toast.autovacuum_multixact_freeze_max_age",
1942 "toast.autovacuum_multixact_freeze_min_age",
1943 "toast.autovacuum_multixact_freeze_table_age",
1944 "toast.autovacuum_vacuum_cost_delay",
1945 "toast.autovacuum_vacuum_cost_limit",
1946 "toast.autovacuum_vacuum_scale_factor",
1947 "toast.autovacuum_vacuum_threshold",
1948 "toast.log_autovacuum_min_duration",
1949 "user_catalog_table",
1953 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
1955 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
1957 completion_info_charp = prev5_wd;
1958 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1960 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1961 COMPLETE_WITH_CONST("INDEX");
1962 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1963 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
1964 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
1965 COMPLETE_WITH_CONST("IDENTITY");
1967 * If we have ALTER TABLE <foo> ATTACH PARTITION, provide a list of
1970 else if (Matches5("ALTER", "TABLE", MatchAny, "ATTACH", "PARTITION"))
1971 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1972 /* Limited completion support for partition bound specification */
1973 else if (TailMatches3("ATTACH", "PARTITION", MatchAny))
1974 COMPLETE_WITH_CONST("FOR VALUES");
1975 else if (TailMatches2("FOR", "VALUES"))
1976 COMPLETE_WITH_LIST2("FROM (", "IN (");
1978 * If we have ALTER TABLE <foo> DETACH PARTITION, provide a list of
1979 * partitions of <foo>.
1981 else if (Matches5("ALTER", "TABLE", MatchAny, "DETACH", "PARTITION"))
1983 completion_info_charp = prev3_wd;
1984 COMPLETE_WITH_QUERY(Query_for_partition_of_table);
1987 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
1988 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
1989 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
1990 /* ALTER TABLESPACE <foo> SET|RESET */
1991 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
1992 COMPLETE_WITH_CONST("(");
1993 /* ALTER TABLESPACE <foo> SET|RESET ( */
1994 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
1995 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
1996 "effective_io_concurrency");
1998 /* ALTER TEXT SEARCH */
1999 else if (Matches3("ALTER", "TEXT", "SEARCH"))
2000 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2001 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
2002 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
2003 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
2004 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
2005 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2006 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
2008 "OWNER TO", "RENAME TO", "SET SCHEMA");
2010 /* complete ALTER TYPE <foo> with actions */
2011 else if (Matches3("ALTER", "TYPE", MatchAny))
2012 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
2014 "OWNER TO", "RENAME", "SET SCHEMA");
2015 /* complete ALTER TYPE <foo> ADD with actions */
2016 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
2017 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
2018 /* ALTER TYPE <foo> RENAME */
2019 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
2020 COMPLETE_WITH_LIST3("ATTRIBUTE", "TO", "VALUE");
2021 /* ALTER TYPE xxx RENAME (ATTRIBUTE|VALUE) yyy */
2022 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE|VALUE", MatchAny))
2023 COMPLETE_WITH_CONST("TO");
2025 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
2028 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
2029 COMPLETE_WITH_ATTR(prev3_wd, "");
2030 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
2031 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
2032 COMPLETE_WITH_CONST("TYPE");
2033 /* complete ALTER GROUP <foo> */
2034 else if (Matches3("ALTER", "GROUP", MatchAny))
2035 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
2036 /* complete ALTER GROUP <foo> ADD|DROP with USER */
2037 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
2038 COMPLETE_WITH_CONST("USER");
2039 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
2040 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
2041 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2044 * If we have ALTER TYPE <sth> RENAME VALUE, provide list of enum values
2046 else if (Matches5("ALTER", "TYPE", MatchAny, "RENAME", "VALUE"))
2047 COMPLETE_WITH_ENUM_VALUE(prev3_wd);
2050 else if (Matches1("BEGIN"))
2051 COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
2053 else if (Matches1("END|ABORT"))
2054 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
2056 else if (Matches1("COMMIT"))
2057 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
2058 /* RELEASE SAVEPOINT */
2059 else if (Matches1("RELEASE"))
2060 COMPLETE_WITH_CONST("SAVEPOINT");
2062 else if (Matches1("ROLLBACK"))
2063 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
2065 else if (Matches1("CLUSTER"))
2066 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
2067 else if (Matches2("CLUSTER", "VERBOSE"))
2068 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2069 /* If we have CLUSTER <sth>, then add "USING" */
2070 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
2071 COMPLETE_WITH_CONST("USING");
2072 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
2073 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
2074 COMPLETE_WITH_CONST("USING");
2075 /* If we have CLUSTER <sth> USING, then add the index as well */
2076 else if (Matches3("CLUSTER", MatchAny, "USING") ||
2077 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
2079 completion_info_charp = prev2_wd;
2080 COMPLETE_WITH_QUERY(Query_for_index_of_table);
2084 else if (Matches1("COMMENT"))
2085 COMPLETE_WITH_CONST("ON");
2086 else if (Matches2("COMMENT", "ON"))
2088 static const char *const list_COMMENT[] =
2089 {"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
2090 "EVENT TRIGGER", "EXTENSION",
2091 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
2092 "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
2093 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
2094 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
2095 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
2097 COMPLETE_WITH_LIST(list_COMMENT);
2099 else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
2100 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2101 else if (Matches3("COMMENT", "ON", "FOREIGN"))
2102 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2103 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
2104 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2105 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
2106 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
2107 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
2108 COMPLETE_WITH_CONST("ON");
2109 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
2111 completion_info_charp = prev2_wd;
2112 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
2114 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
2115 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2116 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
2117 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2118 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
2119 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
2120 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
2121 COMPLETE_WITH_CONST("IS");
2126 * If we have COPY, offer list of tables or "(" (Also cover the analogous
2127 * backslash command).
2129 else if (Matches1("COPY|\\copy"))
2130 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2131 " UNION ALL SELECT '('");
2132 /* If we have COPY BINARY, complete with list of tables */
2133 else if (Matches2("COPY", "BINARY"))
2134 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2135 /* If we have COPY (, complete it with legal commands */
2136 else if (Matches2("COPY|\\copy", "("))
2137 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
2138 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
2139 else if (Matches2("COPY|\\copy", MatchAny) ||
2140 Matches3("COPY", "BINARY", MatchAny))
2141 COMPLETE_WITH_LIST2("FROM", "TO");
2142 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
2143 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
2144 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
2146 completion_charp = "";
2147 matches = completion_matches(text, complete_from_files);
2150 /* Handle COPY [BINARY] <sth> FROM|TO filename */
2151 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
2152 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
2153 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
2156 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
2157 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
2158 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
2159 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
2162 /* CREATE ACCESS METHOD */
2163 /* Complete "CREATE ACCESS METHOD <name>" */
2164 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
2165 COMPLETE_WITH_CONST("TYPE");
2166 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
2167 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
2168 COMPLETE_WITH_CONST("INDEX");
2169 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
2170 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
2171 COMPLETE_WITH_CONST("HANDLER");
2173 /* CREATE DATABASE */
2174 else if (Matches3("CREATE", "DATABASE", MatchAny))
2175 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
2177 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
2178 "LC_COLLATE", "LC_CTYPE");
2180 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2181 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2183 /* CREATE EXTENSION */
2184 /* Complete with available extensions rather than installed ones. */
2185 else if (Matches2("CREATE", "EXTENSION"))
2186 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2187 /* CREATE EXTENSION <name> */
2188 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2189 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2190 /* CREATE EXTENSION <name> VERSION */
2191 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2193 completion_info_charp = prev2_wd;
2194 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2197 /* CREATE FOREIGN */
2198 else if (Matches2("CREATE", "FOREIGN"))
2199 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2201 /* CREATE FOREIGN DATA WRAPPER */
2202 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2203 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2205 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2206 /* First off we complete CREATE UNIQUE with "INDEX" */
2207 else if (TailMatches2("CREATE", "UNIQUE"))
2208 COMPLETE_WITH_CONST("INDEX");
2211 * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
2214 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2215 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2216 " UNION SELECT 'ON'"
2217 " UNION SELECT 'CONCURRENTLY'");
2218 /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
2219 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2220 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2221 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2224 * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
2227 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2228 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2229 " UNION SELECT 'ON'");
2230 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2231 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2232 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2233 COMPLETE_WITH_CONST("ON");
2236 * Complete INDEX <name> ON <table> with a list of table columns (which
2237 * should really be in parens)
2239 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2240 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2241 COMPLETE_WITH_LIST2("(", "USING");
2242 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2243 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2244 COMPLETE_WITH_ATTR(prev2_wd, "");
2245 /* same if you put in USING */
2246 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2247 COMPLETE_WITH_ATTR(prev4_wd, "");
2248 /* Complete USING with an index method */
2249 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2250 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2251 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2252 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2253 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2254 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2255 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2256 COMPLETE_WITH_CONST("(");
2259 /* Complete "CREATE POLICY <name> ON" */
2260 else if (Matches3("CREATE", "POLICY", MatchAny))
2261 COMPLETE_WITH_CONST("ON");
2262 /* Complete "CREATE POLICY <name> ON <table>" */
2263 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2264 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2265 /* Complete "CREATE POLICY <name> ON <table> AS|FOR|TO|USING|WITH CHECK" */
2266 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2267 COMPLETE_WITH_LIST5("AS", "FOR", "TO", "USING (", "WITH CHECK (");
2268 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE */
2269 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS"))
2270 COMPLETE_WITH_LIST2("PERMISSIVE", "RESTRICTIVE");
2271 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR|TO|USING|WITH CHECK */
2272 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny))
2273 COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
2274 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2275 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2276 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2277 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2278 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2279 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2280 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2281 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2282 COMPLETE_WITH_LIST2("TO", "USING (");
2283 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2284 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2285 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2286 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2287 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2288 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2289 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2290 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2291 COMPLETE_WITH_CONST("(");
2292 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2293 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR"))
2294 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2295 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR INSERT TO|WITH CHECK" */
2296 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "INSERT"))
2297 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2298 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR SELECT|DELETE TO|USING" */
2299 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "SELECT|DELETE"))
2300 COMPLETE_WITH_LIST2("TO", "USING (");
2301 /* CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE FOR ALL|UPDATE TO|USING|WITH CHECK */
2302 else if (Matches9("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "FOR", "ALL|UPDATE"))
2303 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2304 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE TO <role>" */
2305 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "TO"))
2306 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2307 /* Complete "CREATE POLICY <name> ON <table> AS PERMISSIVE|RESTRICTIVE USING (" */
2308 else if (Matches8("CREATE", "POLICY", MatchAny, "ON", MatchAny, "AS", MatchAny, "USING"))
2309 COMPLETE_WITH_CONST("(");
2312 /* CREATE PUBLICATION */
2313 else if (Matches3("CREATE", "PUBLICATION", MatchAny))
2314 COMPLETE_WITH_LIST3("FOR TABLE", "FOR ALL TABLES", "WITH (");
2315 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR"))
2316 COMPLETE_WITH_LIST2("TABLE", "ALL TABLES");
2317 /* Complete "CREATE PUBLICATION <name> FOR TABLE <table>" */
2318 else if (Matches4("CREATE", "PUBLICATION", MatchAny, "FOR TABLE"))
2319 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2320 /* Complete "CREATE PUBLICATION <name> [...] WITH" */
2321 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
2322 COMPLETE_WITH_LIST2("PUBLISH", "NOPUBLISH");
2323 else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches3("WITH", "(", MatchAny))
2324 COMPLETE_WITH_LIST3("INSERT", "UPDATE", "DELETE");
2327 /* Complete "CREATE RULE <sth>" with "AS ON" */
2328 else if (Matches3("CREATE", "RULE", MatchAny))
2329 COMPLETE_WITH_CONST("AS ON");
2330 /* Complete "CREATE RULE <sth> AS" with "ON" */
2331 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2332 COMPLETE_WITH_CONST("ON");
2333 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2334 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2335 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2336 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2337 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2338 COMPLETE_WITH_CONST("TO");
2339 /* Complete "AS ON <sth> TO" with a table name */
2340 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2341 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2343 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2344 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2345 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2346 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2347 "CYCLE", "OWNED BY", "START WITH");
2348 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2349 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2350 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2352 /* CREATE SERVER <name> */
2353 else if (Matches3("CREATE", "SERVER", MatchAny))
2354 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2356 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2357 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2358 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2359 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2360 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2361 else if (TailMatches2("CREATE", "UNLOGGED"))
2362 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2363 /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
2364 else if (TailMatches2("PARTITION", "BY"))
2365 COMPLETE_WITH_LIST2("RANGE (", "LIST (");
2366 /* If we have xxx PARTITION OF, provide a list of partitioned tables */
2367 else if (TailMatches2("PARTITION", "OF"))
2368 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_partitioned_tables, "");
2369 /* Limited completion support for partition bound specification */
2370 else if (TailMatches3("PARTITION", "OF", MatchAny))
2371 COMPLETE_WITH_CONST("FOR VALUES");
2373 /* CREATE TABLESPACE */
2374 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2375 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2376 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2377 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2378 COMPLETE_WITH_CONST("LOCATION");
2380 /* CREATE TEXT SEARCH */
2381 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2382 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2383 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2384 COMPLETE_WITH_CONST("(");
2386 /* CREATE SUBSCRIPTION */
2387 else if (Matches3("CREATE", "SUBSCRIPTION", MatchAny))
2388 COMPLETE_WITH_CONST("CONNECTION");
2389 else if (Matches5("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION", MatchAny))
2390 COMPLETE_WITH_CONST("PUBLICATION");
2391 else if (Matches6("CREATE", "SUBSCRIPTION", MatchAny, "CONNECTION",
2392 MatchAny, "PUBLICATION"))
2394 /* complete with nothing here as this refers to remote publications */
2396 /* Complete "CREATE SUBSCRIPTION <name> ... WITH ( <opt>" */
2397 else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
2398 COMPLETE_WITH_LIST5("ENABLED", "DISABLED", "CREATE SLOT",
2399 "NOCREATE SLOT", "SLOT NAME");
2401 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2402 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2403 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2404 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2405 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2406 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2407 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2408 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2409 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2410 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2411 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2412 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2413 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2414 COMPLETE_WITH_LIST2("ON", "OR");
2417 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2420 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2421 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2422 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2423 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2424 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2425 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("ON", MatchAny))
2426 COMPLETE_WITH_LIST7("NOT DEFERRABLE", "DEFERRABLE", "INITIALLY",
2427 "REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2428 else if (HeadMatches2("CREATE", "TRIGGER") &&
2429 (TailMatches1("DEFERRABLE") || TailMatches2("INITIALLY", "IMMEDIATE|DEFERRED")))
2430 COMPLETE_WITH_LIST4("REFERENCING", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2431 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("REFERENCING"))
2432 COMPLETE_WITH_LIST2("OLD TABLE", "NEW TABLE");
2433 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("OLD|NEW", "TABLE"))
2434 COMPLETE_WITH_CONST("AS");
2435 else if (HeadMatches2("CREATE", "TRIGGER") &&
2436 (TailMatches5("REFERENCING", "OLD", "TABLE", "AS", MatchAny) ||
2437 TailMatches4("REFERENCING", "OLD", "TABLE", MatchAny)))
2438 COMPLETE_WITH_LIST4("NEW TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2439 else if (HeadMatches2("CREATE", "TRIGGER") &&
2440 (TailMatches5("REFERENCING", "NEW", "TABLE", "AS", MatchAny) ||
2441 TailMatches4("REFERENCING", "NEW", "TABLE", MatchAny)))
2442 COMPLETE_WITH_LIST4("OLD TABLE", "FOR", "WHEN (", "EXECUTE PROCEDURE");
2443 else if (HeadMatches2("CREATE", "TRIGGER") &&
2444 (TailMatches9("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2445 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", "AS", MatchAny) ||
2446 TailMatches8("REFERENCING", "OLD|NEW", "TABLE", "AS", MatchAny, "OLD|NEW", "TABLE", MatchAny) ||
2447 TailMatches7("REFERENCING", "OLD|NEW", "TABLE", MatchAny, "OLD|NEW", "TABLE", MatchAny)))
2448 COMPLETE_WITH_LIST3("FOR", "WHEN (", "EXECUTE PROCEDURE");
2449 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("FOR"))
2450 COMPLETE_WITH_LIST3("EACH", "ROW", "STATEMENT");
2451 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("FOR", "EACH"))
2452 COMPLETE_WITH_LIST2("ROW", "STATEMENT");
2453 else if (HeadMatches2("CREATE", "TRIGGER") &&
2454 (TailMatches3("FOR", "EACH", "ROW|STATEMENT") ||
2455 TailMatches2("FOR", "ROW|STATEMENT")))
2456 COMPLETE_WITH_LIST2("WHEN (", "EXECUTE PROCEDURE");
2457 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2458 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2459 COMPLETE_WITH_CONST("PROCEDURE");
2460 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches2("EXECUTE", "PROCEDURE"))
2461 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2463 /* CREATE ROLE,USER,GROUP <name> */
2464 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2465 !TailMatches2("USER", "MAPPING"))
2467 static const char *const list_CREATEROLE[] =
2468 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2469 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2470 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2471 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2472 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2473 "VALID UNTIL", "WITH", NULL};
2475 COMPLETE_WITH_LIST(list_CREATEROLE);
2478 /* CREATE ROLE,USER,GROUP <name> WITH */
2479 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2481 /* Similar to the above, but don't complete "WITH" again. */
2482 static const char *const list_CREATEROLE_WITH[] =
2483 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2484 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2485 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2486 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2487 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2488 "VALID UNTIL", NULL};
2490 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2494 * complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
2497 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
2498 COMPLETE_WITH_CONST("PASSWORD");
2499 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2500 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2501 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2503 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2504 /* Complete CREATE VIEW <name> with AS */
2505 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2506 COMPLETE_WITH_CONST("AS");
2507 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2508 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2509 COMPLETE_WITH_CONST("SELECT");
2511 /* CREATE MATERIALIZED VIEW */
2512 else if (Matches2("CREATE", "MATERIALIZED"))
2513 COMPLETE_WITH_CONST("VIEW");
2514 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2515 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2516 COMPLETE_WITH_CONST("AS");
2517 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2518 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2519 COMPLETE_WITH_CONST("SELECT");
2521 /* CREATE EVENT TRIGGER */
2522 else if (Matches2("CREATE", "EVENT"))
2523 COMPLETE_WITH_CONST("TRIGGER");
2524 /* Complete CREATE EVENT TRIGGER <name> with ON */
2525 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2526 COMPLETE_WITH_CONST("ON");
2527 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2528 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2529 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2532 else if (Matches1("DEALLOCATE"))
2533 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2536 else if (Matches2("DECLARE", MatchAny))
2537 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2539 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2540 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2542 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2543 /* ... despite which, only complete DELETE with FROM at start of line */
2544 else if (Matches1("DELETE"))
2545 COMPLETE_WITH_CONST("FROM");
2546 /* Complete DELETE FROM with a list of tables */
2547 else if (TailMatches2("DELETE", "FROM"))
2548 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2549 /* Complete DELETE FROM <table> */
2550 else if (TailMatches3("DELETE", "FROM", MatchAny))
2551 COMPLETE_WITH_LIST2("USING", "WHERE");
2552 /* XXX: implement tab completion for DELETE ... USING */
2555 else if (Matches1("DISCARD"))
2556 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2559 else if (Matches1("DO"))
2560 COMPLETE_WITH_CONST("LANGUAGE");
2563 /* Complete DROP object with CASCADE / RESTRICT */
2564 else if (Matches3("DROP",
2565 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|PUBLICATION|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
2567 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2568 (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2569 ends_with(prev_wd, ')')) ||
2570 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2571 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2572 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2573 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2574 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2576 /* help completing some of the variants */
2577 else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2578 COMPLETE_WITH_CONST("(");
2579 else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2580 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2581 else if (Matches2("DROP", "FOREIGN"))
2582 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2585 else if (Matches2("DROP", "INDEX"))
2586 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2587 " UNION SELECT 'CONCURRENTLY'");
2588 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2589 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2590 else if (Matches3("DROP", "INDEX", MatchAny))
2591 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2592 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2593 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2595 /* DROP MATERIALIZED VIEW */
2596 else if (Matches2("DROP", "MATERIALIZED"))
2597 COMPLETE_WITH_CONST("VIEW");
2598 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2599 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2602 else if (Matches2("DROP", "OWNED"))
2603 COMPLETE_WITH_CONST("BY");
2604 else if (Matches3("DROP", "OWNED", "BY"))
2605 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2607 else if (Matches3("DROP", "TEXT", "SEARCH"))
2608 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2611 else if (Matches3("DROP", "TRIGGER", MatchAny))
2612 COMPLETE_WITH_CONST("ON");
2613 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2615 completion_info_charp = prev2_wd;
2616 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2618 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2619 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2621 /* DROP ACCESS METHOD */
2622 else if (Matches2("DROP", "ACCESS"))
2623 COMPLETE_WITH_CONST("METHOD");
2624 else if (Matches3("DROP", "ACCESS", "METHOD"))
2625 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2627 /* DROP EVENT TRIGGER */
2628 else if (Matches2("DROP", "EVENT"))
2629 COMPLETE_WITH_CONST("TRIGGER");
2630 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2631 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2633 /* DROP POLICY <name> */
2634 else if (Matches2("DROP", "POLICY"))
2635 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2636 /* DROP POLICY <name> ON */
2637 else if (Matches3("DROP", "POLICY", MatchAny))
2638 COMPLETE_WITH_CONST("ON");
2639 /* DROP POLICY <name> ON <table> */
2640 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2642 completion_info_charp = prev2_wd;
2643 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2647 else if (Matches3("DROP", "RULE", MatchAny))
2648 COMPLETE_WITH_CONST("ON");
2649 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2651 completion_info_charp = prev2_wd;
2652 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2654 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2655 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2658 else if (Matches1("EXECUTE"))
2659 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2664 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2666 else if (Matches1("EXPLAIN"))
2667 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2668 "ANALYZE", "VERBOSE");
2669 else if (Matches2("EXPLAIN", "ANALYZE"))
2670 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2672 else if (Matches2("EXPLAIN", "VERBOSE") ||
2673 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2674 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2677 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2678 else if (Matches1("FETCH|MOVE"))
2679 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2680 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2681 else if (Matches2("FETCH|MOVE", MatchAny))
2682 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2685 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2686 * but we may as well tab-complete both: perhaps some users prefer one
2687 * variant or the other.
2689 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2690 COMPLETE_WITH_LIST2("FROM", "IN");
2692 /* FOREIGN DATA WRAPPER */
2693 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2694 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2695 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2696 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2697 /* applies in CREATE SERVER */
2698 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2699 HeadMatches2("CREATE", "SERVER"))
2700 COMPLETE_WITH_CONST("OPTIONS");
2703 else if (TailMatches2("FOREIGN", "TABLE") &&
2704 !TailMatches3("CREATE", MatchAny, MatchAny))
2705 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2707 /* FOREIGN SERVER */
2708 else if (TailMatches2("FOREIGN", "SERVER"))
2709 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2712 * GRANT and REVOKE are allowed inside CREATE SCHEMA and
2713 * ALTER DEFAULT PRIVILEGES, so use TailMatches
2715 /* Complete GRANT/REVOKE with a list of roles and privileges */
2716 else if (TailMatches1("GRANT|REVOKE"))
2718 * With ALTER DEFAULT PRIVILEGES, restrict completion
2719 * to grantable privileges (can't grant roles)
2721 if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
2722 COMPLETE_WITH_LIST10("SELECT", "INSERT", "UPDATE",
2723 "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
2724 "EXECUTE", "USAGE", "ALL");
2726 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2727 " UNION SELECT 'SELECT'"
2728 " UNION SELECT 'INSERT'"
2729 " UNION SELECT 'UPDATE'"
2730 " UNION SELECT 'DELETE'"
2731 " UNION SELECT 'TRUNCATE'"
2732 " UNION SELECT 'REFERENCES'"
2733 " UNION SELECT 'TRIGGER'"
2734 " UNION SELECT 'CREATE'"
2735 " UNION SELECT 'CONNECT'"
2736 " UNION SELECT 'TEMPORARY'"
2737 " UNION SELECT 'EXECUTE'"
2738 " UNION SELECT 'USAGE'"
2739 " UNION SELECT 'ALL'");
2742 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2745 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2747 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2748 COMPLETE_WITH_CONST("ON");
2749 else if (TailMatches2("GRANT", MatchAny))
2750 COMPLETE_WITH_CONST("TO");
2752 COMPLETE_WITH_CONST("FROM");
2756 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2759 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2760 * result via UNION; seems to work intuitively.
2762 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2763 * here will only work if the privilege list contains exactly one
2766 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2768 * With ALTER DEFAULT PRIVILEGES, restrict completion
2769 * to the kinds of objects supported.
2771 if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
2772 COMPLETE_WITH_LIST4("TABLES", "SEQUENCES", "FUNCTIONS", "TYPES");
2774 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2775 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2776 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2777 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2778 " UNION SELECT 'DATABASE'"
2779 " UNION SELECT 'DOMAIN'"
2780 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2781 " UNION SELECT 'FOREIGN SERVER'"
2782 " UNION SELECT 'FUNCTION'"
2783 " UNION SELECT 'LANGUAGE'"
2784 " UNION SELECT 'LARGE OBJECT'"
2785 " UNION SELECT 'SCHEMA'"
2786 " UNION SELECT 'SEQUENCE'"
2787 " UNION SELECT 'TABLE'"
2788 " UNION SELECT 'TABLESPACE'"
2789 " UNION SELECT 'TYPE'");
2791 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2792 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2793 "TABLES IN SCHEMA");
2795 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2796 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2799 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2800 * appropriate objects.
2802 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2804 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2806 if (TailMatches1("DATABASE"))
2807 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2808 else if (TailMatches1("DOMAIN"))
2809 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2810 else if (TailMatches1("FUNCTION"))
2811 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2812 else if (TailMatches1("LANGUAGE"))
2813 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2814 else if (TailMatches1("SCHEMA"))
2815 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2816 else if (TailMatches1("SEQUENCE"))
2817 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2818 else if (TailMatches1("TABLE"))
2819 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2820 else if (TailMatches1("TABLESPACE"))
2821 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2822 else if (TailMatches1("TYPE"))
2823 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2824 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2825 COMPLETE_WITH_CONST("TO");
2827 COMPLETE_WITH_CONST("FROM");
2831 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2832 * CURRENT_USER, or SESSION_USER.
2834 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2835 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2836 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2837 /* Complete "ALTER DEFAULT PRIVILEGES ... GRANT/REVOKE ... TO/FROM */
2838 else if (HeadMatches3("ALTER","DEFAULT", "PRIVILEGES") && TailMatches1("TO|FROM"))
2839 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2840 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2841 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2842 COMPLETE_WITH_CONST("TO");
2843 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2844 COMPLETE_WITH_CONST("FROM");
2846 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2847 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2849 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2850 COMPLETE_WITH_CONST("TO");
2852 COMPLETE_WITH_CONST("FROM");
2855 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2856 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2858 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2859 COMPLETE_WITH_CONST("TO");
2861 COMPLETE_WITH_CONST("FROM");
2864 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
2865 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
2867 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2868 COMPLETE_WITH_CONST("TO");
2870 COMPLETE_WITH_CONST("FROM");
2874 else if (TailMatches3("FROM", MatchAny, "GROUP"))
2875 COMPLETE_WITH_CONST("BY");
2877 /* IMPORT FOREIGN SCHEMA */
2878 else if (Matches1("IMPORT"))
2879 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
2880 else if (Matches2("IMPORT", "FOREIGN"))
2881 COMPLETE_WITH_CONST("SCHEMA");
2883 /* INSERT --- can be inside EXPLAIN, RULE, etc */
2884 /* Complete INSERT with "INTO" */
2885 else if (TailMatches1("INSERT"))
2886 COMPLETE_WITH_CONST("INTO");
2887 /* Complete INSERT INTO with table names */
2888 else if (TailMatches2("INSERT", "INTO"))
2889 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2890 /* Complete "INSERT INTO <table> (" with attribute names */
2891 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
2892 COMPLETE_WITH_ATTR(prev2_wd, "");
2895 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2896 * "TABLE" or "DEFAULT VALUES"
2898 else if (TailMatches3("INSERT", "INTO", MatchAny))
2899 COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
2902 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
2905 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
2906 ends_with(prev_wd, ')'))
2907 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
2909 /* Insert an open parenthesis after "VALUES" */
2910 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
2911 COMPLETE_WITH_CONST("(");
2914 /* Complete LOCK [TABLE] with a list of tables */
2915 else if (Matches1("LOCK"))
2916 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2917 " UNION SELECT 'TABLE'");
2918 else if (Matches2("LOCK", "TABLE"))
2919 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2921 /* For the following, handle the case of a single table only for now */
2923 /* Complete LOCK [TABLE] <table> with "IN" */
2924 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
2925 Matches3("LOCK", "TABLE", MatchAny))
2926 COMPLETE_WITH_CONST("IN");
2928 /* Complete LOCK [TABLE] <table> IN with a lock mode */
2929 else if (Matches3("LOCK", MatchAny, "IN") ||
2930 Matches4("LOCK", "TABLE", MatchAny, "IN"))
2931 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
2932 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
2933 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
2934 "SHARE ROW EXCLUSIVE MODE",
2935 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
2937 /* Complete LOCK [TABLE] <table> IN ACCESS|ROW with rest of lock mode */
2938 else if (Matches4("LOCK", MatchAny, "IN", "ACCESS|ROW") ||
2939 Matches5("LOCK", "TABLE", MatchAny, "IN", "ACCESS|ROW"))
2940 COMPLETE_WITH_LIST2("EXCLUSIVE MODE", "SHARE MODE");
2942 /* Complete LOCK [TABLE] <table> IN SHARE with rest of lock mode */
2943 else if (Matches4("LOCK", MatchAny, "IN", "SHARE") ||
2944 Matches5("LOCK", "TABLE", MatchAny, "IN", "SHARE"))
2945 COMPLETE_WITH_LIST3("MODE", "ROW EXCLUSIVE MODE",
2946 "UPDATE EXCLUSIVE MODE");
2948 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
2949 else if (TailMatches1("NOTIFY"))
2950 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'");
2953 else if (TailMatches1("OPTIONS"))
2954 COMPLETE_WITH_CONST("(");
2956 /* OWNER TO - complete with available roles */
2957 else if (TailMatches2("OWNER", "TO"))
2958 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2961 else if (TailMatches3("FROM", MatchAny, "ORDER"))
2962 COMPLETE_WITH_CONST("BY");
2963 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
2964 COMPLETE_WITH_ATTR(prev3_wd, "");
2967 else if (Matches3("PREPARE", MatchAny, "AS"))
2968 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
2971 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
2972 * managers, not for manual use in interactive sessions.
2975 /* REASSIGN OWNED BY xxx TO yyy */
2976 else if (Matches1("REASSIGN"))
2977 COMPLETE_WITH_CONST("OWNED BY");
2978 else if (Matches2("REASSIGN", "OWNED"))
2979 COMPLETE_WITH_CONST("BY");
2980 else if (Matches3("REASSIGN", "OWNED", "BY"))
2981 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2982 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
2983 COMPLETE_WITH_CONST("TO");
2984 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
2985 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2987 /* REFRESH MATERIALIZED VIEW */
2988 else if (Matches1("REFRESH"))
2989 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
2990 else if (Matches2("REFRESH", "MATERIALIZED"))
2991 COMPLETE_WITH_CONST("VIEW");
2992 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
2993 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
2994 " UNION SELECT 'CONCURRENTLY'");
2995 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
2996 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2997 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
2998 COMPLETE_WITH_CONST("WITH");
2999 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
3000 COMPLETE_WITH_CONST("WITH");
3001 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
3002 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3003 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
3004 COMPLETE_WITH_LIST2("NO DATA", "DATA");
3005 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
3006 COMPLETE_WITH_CONST("DATA");
3007 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
3008 COMPLETE_WITH_CONST("DATA");
3011 else if (Matches1("REINDEX"))
3012 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
3013 else if (Matches2("REINDEX", "TABLE"))
3014 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3015 else if (Matches2("REINDEX", "INDEX"))
3016 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3017 else if (Matches2("REINDEX", "SCHEMA"))
3018 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3019 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
3020 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3022 /* SECURITY LABEL */
3023 else if (Matches1("SECURITY"))
3024 COMPLETE_WITH_CONST("LABEL");
3025 else if (Matches2("SECURITY", "LABEL"))
3026 COMPLETE_WITH_LIST2("ON", "FOR");
3027 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
3028 COMPLETE_WITH_CONST("ON");
3029 else if (Matches3("SECURITY", "LABEL", "ON") ||
3030 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
3032 static const char *const list_SECURITY_LABEL[] =
3033 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
3034 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
3035 "MATERIALIZED VIEW", "LANGUAGE", "ROLE", "SCHEMA",
3036 "SEQUENCE", "TABLESPACE", "TYPE", "VIEW", NULL};
3038 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
3040 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
3041 COMPLETE_WITH_CONST("IS");
3046 /* SET, RESET, SHOW */
3047 /* Complete with a variable name */
3048 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
3049 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
3050 else if (Matches1("SHOW"))
3051 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
3052 /* Complete "SET TRANSACTION" */
3053 else if (Matches2("SET", "TRANSACTION"))
3054 COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3055 else if (Matches2("BEGIN|START", "TRANSACTION") ||
3056 Matches2("BEGIN", "WORK") ||
3057 Matches1("BEGIN") ||
3058 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
3059 COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
3060 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
3061 Matches2("BEGIN", "NOT") ||
3062 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
3063 COMPLETE_WITH_CONST("DEFERRABLE");
3064 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
3065 Matches2("BEGIN", "ISOLATION") ||
3066 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
3067 COMPLETE_WITH_CONST("LEVEL");
3068 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
3069 Matches3("BEGIN", "ISOLATION", "LEVEL") ||
3070 Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
3071 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
3072 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
3073 Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
3074 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
3075 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
3076 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
3077 Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
3078 Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
3079 COMPLETE_WITH_CONST("READ");
3080 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
3081 Matches2("BEGIN", "READ") ||
3082 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
3083 COMPLETE_WITH_LIST2("ONLY", "WRITE");
3084 /* SET CONSTRAINTS */
3085 else if (Matches2("SET", "CONSTRAINTS"))
3086 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
3087 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
3088 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
3089 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
3090 /* Complete SET ROLE */
3091 else if (Matches2("SET", "ROLE"))
3092 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3093 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
3094 else if (Matches2("SET", "SESSION"))
3095 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
3096 /* Complete SET SESSION AUTHORIZATION with username */
3097 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
3098 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
3099 /* Complete RESET SESSION with AUTHORIZATION */
3100 else if (Matches2("RESET", "SESSION"))
3101 COMPLETE_WITH_CONST("AUTHORIZATION");
3102 /* Complete SET <var> with "TO" */
3103 else if (Matches2("SET", MatchAny))
3104 COMPLETE_WITH_CONST("TO");
3105 /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
3106 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
3107 TailMatches2("SET", MatchAny))
3108 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
3109 /* Suggest possible variable values */
3110 else if (TailMatches3("SET", MatchAny, "TO|="))
3112 /* special cased code for individual GUCs */
3113 if (TailMatches2("DateStyle", "TO|="))
3115 static const char *const my_list[] =
3116 {"ISO", "SQL", "Postgres", "German",
3117 "YMD", "DMY", "MDY",
3118 "US", "European", "NonEuropean",
3121 COMPLETE_WITH_LIST(my_list);
3123 else if (TailMatches2("search_path", "TO|="))
3124 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
3125 " AND nspname not like 'pg\\_toast%%' "
3126 " AND nspname not like 'pg\\_temp%%' "
3127 " UNION SELECT 'DEFAULT' ");
3130 /* generic, type based, GUC support */
3131 char *guctype = get_guctype(prev2_wd);
3133 if (guctype && strcmp(guctype, "enum") == 0)
3135 char querybuf[1024];
3137 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
3138 COMPLETE_WITH_QUERY(querybuf);
3140 else if (guctype && strcmp(guctype, "bool") == 0)
3141 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
3142 "1", "0", "DEFAULT");
3144 COMPLETE_WITH_CONST("DEFAULT");
3151 /* START TRANSACTION */
3152 else if (Matches1("START"))
3153 COMPLETE_WITH_CONST("TRANSACTION");
3155 /* TABLE, but not TABLE embedded in other commands */
3156 else if (Matches1("TABLE"))
3157 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3160 else if (TailMatches1("TABLESAMPLE"))
3161 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
3162 else if (TailMatches2("TABLESAMPLE", MatchAny))
3163 COMPLETE_WITH_CONST("(");
3166 else if (Matches1("TRUNCATE"))
3167 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3170 else if (Matches1("UNLISTEN"))
3171 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 '*'");
3173 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
3174 /* If prev. word is UPDATE suggest a list of tables */
3175 else if (TailMatches1("UPDATE"))
3176 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
3177 /* Complete UPDATE <table> with "SET" */
3178 else if (TailMatches2("UPDATE", MatchAny))
3179 COMPLETE_WITH_CONST("SET");
3180 /* Complete UPDATE <table> SET with list of attributes */
3181 else if (TailMatches3("UPDATE", MatchAny, "SET"))
3182 COMPLETE_WITH_ATTR(prev2_wd, "");
3183 /* UPDATE <table> SET <attr> = */
3184 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
3185 COMPLETE_WITH_CONST("=");
3188 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
3189 COMPLETE_WITH_CONST("FOR");
3190 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
3191 COMPLETE_WITH_QUERY(Query_for_list_of_roles
3192 " UNION SELECT 'CURRENT_USER'"
3193 " UNION SELECT 'PUBLIC'"
3194 " UNION SELECT 'USER'");
3195 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
3196 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3197 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
3198 COMPLETE_WITH_CONST("SERVER");
3199 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
3200 COMPLETE_WITH_CONST("OPTIONS");
3203 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
3204 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
3206 else if (Matches1("VACUUM"))
3207 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3208 " UNION SELECT 'FULL'"
3209 " UNION SELECT 'FREEZE'"
3210 " UNION SELECT 'ANALYZE'"
3211 " UNION SELECT 'VERBOSE'");
3212 else if (Matches2("VACUUM", "FULL|FREEZE"))
3213 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3214 " UNION SELECT 'ANALYZE'"
3215 " UNION SELECT 'VERBOSE'");
3216 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
3217 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3218 " UNION SELECT 'VERBOSE'");
3219 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
3220 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3221 " UNION SELECT 'ANALYZE'");
3222 else if (Matches2("VACUUM", "VERBOSE"))
3223 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3224 " UNION SELECT 'ANALYZE'");
3225 else if (Matches2("VACUUM", "ANALYZE"))
3226 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
3227 " UNION SELECT 'VERBOSE'");
3228 else if (HeadMatches1("VACUUM"))
3229 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
3231 /* WITH [RECURSIVE] */
3234 * Only match when WITH is the first word, as WITH may appear in many
3237 else if (Matches1("WITH"))
3238 COMPLETE_WITH_CONST("RECURSIVE");
3241 /* Complete with list of tables */
3242 else if (Matches1("ANALYZE"))
3243 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
3246 /* Simple case of the word before the where being the table name */
3247 else if (TailMatches2(MatchAny, "WHERE"))
3248 COMPLETE_WITH_ATTR(prev2_wd, "");
3251 /* TODO: also include SRF ? */
3252 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
3253 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3256 else if (TailMatches1("JOIN"))
3257 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3259 /* Backslash commands */
3260 /* TODO: \dc \dd \dl */
3261 else if (TailMatchesCS1("\\?"))
3262 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
3263 else if (TailMatchesCS1("\\connect|\\c"))
3265 if (!recognized_connection_string(text))
3266 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3268 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
3270 if (!recognized_connection_string(prev_wd))
3271 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3273 else if (TailMatchesCS1("\\da*"))
3274 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
3275 else if (TailMatchesCS1("\\dA*"))
3276 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
3277 else if (TailMatchesCS1("\\db*"))
3278 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
3279 else if (TailMatchesCS1("\\dD*"))
3280 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
3281 else if (TailMatchesCS1("\\des*"))
3282 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3283 else if (TailMatchesCS1("\\deu*"))
3284 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
3285 else if (TailMatchesCS1("\\dew*"))
3286 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
3287 else if (TailMatchesCS1("\\df*"))
3288 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3290 else if (TailMatchesCS1("\\dFd*"))
3291 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
3292 else if (TailMatchesCS1("\\dFp*"))
3293 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
3294 else if (TailMatchesCS1("\\dFt*"))
3295 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
3296 /* must be at end of \dF alternatives: */
3297 else if (TailMatchesCS1("\\dF*"))
3298 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
3300 else if (TailMatchesCS1("\\di*"))
3301 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
3302 else if (TailMatchesCS1("\\dL*"))
3303 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
3304 else if (TailMatchesCS1("\\dn*"))
3305 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3306 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
3307 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
3308 else if (TailMatchesCS1("\\ds*"))
3309 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3310 else if (TailMatchesCS1("\\dt*"))
3311 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
3312 else if (TailMatchesCS1("\\dT*"))
3313 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
3314 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
3315 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3316 else if (TailMatchesCS1("\\dv*"))
3317 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3318 else if (TailMatchesCS1("\\dx*"))
3319 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
3320 else if (TailMatchesCS1("\\dm*"))
3321 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
3322 else if (TailMatchesCS1("\\dE*"))
3323 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
3324 else if (TailMatchesCS1("\\dy*"))
3325 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
3327 /* must be at end of \d alternatives: */
3328 else if (TailMatchesCS1("\\d*"))
3329 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
3331 else if (TailMatchesCS1("\\ef"))
3332 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3333 else if (TailMatchesCS1("\\ev"))
3334 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3336 else if (TailMatchesCS1("\\encoding"))
3337 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
3338 else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
3339 COMPLETE_WITH_LIST(sql_commands);
3340 else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
3341 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
3342 else if (TailMatchesCS1("\\password"))
3343 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
3344 else if (TailMatchesCS1("\\pset"))
3346 static const char *const my_list[] =
3347 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3348 "footer", "format", "linestyle", "null", "numericlocale",
3349 "pager", "pager_min_lines", "recordsep", "recordsep_zero",
3350 "tableattr", "title", "tuples_only", "unicode_border_linestyle",
3351 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3353 COMPLETE_WITH_LIST_CS(my_list);
3355 else if (TailMatchesCS2("\\pset", MatchAny))
3357 if (TailMatchesCS1("format"))
3359 static const char *const my_list[] =
3360 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3361 "latex", "latex-longtable", "troff-ms", NULL};
3363 COMPLETE_WITH_LIST_CS(my_list);
3365 else if (TailMatchesCS1("linestyle"))
3366 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3367 else if (TailMatchesCS1("unicode_border_linestyle|"
3368 "unicode_column_linestyle|"
3369 "unicode_header_linestyle"))
3370 COMPLETE_WITH_LIST_CS2("single", "double");
3372 else if (TailMatchesCS1("\\unset"))
3374 matches = complete_from_variables(text, "", "", true);
3376 else if (TailMatchesCS1("\\set"))
3378 matches = complete_from_variables(text, "", "", false);
3380 else if (TailMatchesCS2("\\set", MatchAny))
3382 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3383 "SINGLELINE|SINGLESTEP"))
3384 COMPLETE_WITH_LIST_CS2("on", "off");
3385 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3386 COMPLETE_WITH_LIST_CS4("lower", "upper",
3387 "preserve-lower", "preserve-upper");
3388 else if (TailMatchesCS1("ECHO"))
3389 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3390 else if (TailMatchesCS1("ECHO_HIDDEN"))
3391 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3392 else if (TailMatchesCS1("HISTCONTROL"))
3393 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3394 "ignoreboth", "none");
3395 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3396 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3397 else if (TailMatchesCS1("SHOW_CONTEXT"))
3398 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3399 else if (TailMatchesCS1("VERBOSITY"))
3400 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3402 else if (TailMatchesCS1("\\sf*"))
3403 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3404 else if (TailMatchesCS1("\\sv*"))
3405 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3406 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3407 "\\ir|\\include_relative|\\o|\\out|"
3408 "\\s|\\w|\\write|\\lo_import"))
3410 completion_charp = "\\";
3411 matches = completion_matches(text, complete_from_files);
3415 * Finally, we look through the list of "things", such as TABLE, INDEX and
3416 * check if that was the previous word. If so, execute the query to get a
3423 for (i = 0; words_after_create[i].name; i++)
3425 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3427 if (words_after_create[i].query)
3428 COMPLETE_WITH_QUERY(words_after_create[i].query);
3429 else if (words_after_create[i].squery)
3430 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3438 * If we still don't have anything to match we have to fabricate some sort
3439 * of default list. If we were to just return NULL, readline automatically
3440 * attempts filename completion, and that's usually no good.
3442 if (matches == NULL)
3444 COMPLETE_WITH_CONST("");
3445 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3446 rl_completion_append_character = '\0';
3451 free(previous_words);
3454 /* Return our Grand List O' Matches */
3460 * GENERATOR FUNCTIONS
3462 * These functions do all the actual work of completing the input. They get
3463 * passed the text so far and the count how many times they have been called
3464 * so far with the same text.
3465 * If you read the above carefully, you'll see that these don't get called
3466 * directly but through the readline interface.
3467 * The return value is expected to be the full completion of the text, going
3468 * through a list each time, or NULL if there are no more matches. The string
3469 * will be free()'d by readline, so you must run it through strdup() or
3470 * something of that sort.
3474 * Common routine for create_command_generator and drop_command_generator.
3475 * Entries that have 'excluded' flags are not returned.
3478 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3480 static int list_index,
3484 /* If this is the first time for this completion, init some values */
3488 string_length = strlen(text);
3491 /* find something that matches */
3492 while ((name = words_after_create[list_index++].name))
3494 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3495 !(words_after_create[list_index - 1].flags & excluded))
3496 return pg_strdup_keyword_case(name, text);
3498 /* if nothing matches, return NULL */
3503 * This one gives you one from a list of things you can put after CREATE
3507 create_command_generator(const char *text, int state)
3509 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3513 * This function gives you a list of things you can put after a DROP command.
3516 drop_command_generator(const char *text, int state)
3518 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3521 /* The following two functions are wrappers for _complete_from_query */
3524 complete_from_query(const char *text, int state)
3526 return _complete_from_query(0, text, state);
3530 complete_from_schema_query(const char *text, int state)
3532 return _complete_from_query(1, text, state);
3537 * This creates a list of matching things, according to a query pointed to
3538 * by completion_charp.
3539 * The query can be one of two kinds:
3541 * 1. A simple query which must contain a %d and a %s, which will be replaced
3542 * by the string length of the text and the text itself. The query may also
3543 * have up to four more %s in it; the first two such will be replaced by the
3544 * value of completion_info_charp, the next two by the value of
3545 * completion_info_charp2.
3547 * 2. A schema query used for completion of both schema and relation names.
3548 * These are more complex and must contain in the following order:
3549 * %d %s %d %s %d %s %s %d %s
3550 * where %d is the string length of the text and %s the text itself.
3552 * It is assumed that strings should be escaped to become SQL literals
3553 * (that is, what is in the query is actually ... '%s' ...)
3555 * See top of file for examples of both kinds of query.
3558 _complete_from_query(int is_schema_query, const char *text, int state)
3560 static int list_index,
3562 static PGresult *result = NULL;
3565 * If this is the first time for this completion, we fetch a list of our
3566 * "things" from the backend.
3570 PQExpBufferData query_buffer;
3573 char *e_info_charp2;
3574 const char *pstr = text;
3575 int char_length = 0;
3578 byte_length = strlen(text);
3581 * Count length as number of characters (not bytes), for passing to
3587 pstr += PQmblen(pstr, pset.encoding);
3590 /* Free any prior result */
3594 /* Set up suitably-escaped copies of textual inputs */
3595 e_text = escape_string(text);
3597 if (completion_info_charp)
3598 e_info_charp = escape_string(completion_info_charp);
3600 e_info_charp = NULL;
3602 if (completion_info_charp2)
3603 e_info_charp2 = escape_string(completion_info_charp2);
3605 e_info_charp2 = NULL;
3607 initPQExpBuffer(&query_buffer);
3609 if (is_schema_query)
3611 /* completion_squery gives us the pieces to assemble */
3612 const char *qualresult = completion_squery->qualresult;
3614 if (qualresult == NULL)
3615 qualresult = completion_squery->result;
3617 /* Get unqualified names matching the input-so-far */
3618 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3619 completion_squery->result,
3620 completion_squery->catname);
3621 if (completion_squery->selcondition)
3622 appendPQExpBuffer(&query_buffer, "%s AND ",
3623 completion_squery->selcondition);
3624 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3625 completion_squery->result,
3626 char_length, e_text);
3627 appendPQExpBuffer(&query_buffer, " AND %s",
3628 completion_squery->viscondition);
3631 * When fetching relation names, suppress system catalogs unless
3632 * the input-so-far begins with "pg_". This is a compromise
3633 * between not offering system catalogs for completion at all, and
3634 * having them swamp the result when the input is just "p".
3636 if (strcmp(completion_squery->catname,
3637 "pg_catalog.pg_class c") == 0 &&
3638 strncmp(text, "pg_", 3) !=0)
3640 appendPQExpBufferStr(&query_buffer,
3641 " AND c.relnamespace <> (SELECT oid FROM"
3642 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3646 * Add in matching schema names, but only if there is more than
3647 * one potential match among schema names.
3649 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3650 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3651 "FROM pg_catalog.pg_namespace n "
3652 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3653 char_length, e_text);
3654 appendPQExpBuffer(&query_buffer,
3655 " AND (SELECT pg_catalog.count(*)"
3656 " FROM pg_catalog.pg_namespace"
3657 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3658 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3659 char_length, e_text);
3662 * Add in matching qualified names, but only if there is exactly
3663 * one schema matching the input-so-far.
3665 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3666 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3667 "FROM %s, pg_catalog.pg_namespace n "
3668 "WHERE %s = n.oid AND ",
3670 completion_squery->catname,
3671 completion_squery->namespace);
3672 if (completion_squery->selcondition)
3673 appendPQExpBuffer(&query_buffer, "%s AND ",
3674 completion_squery->selcondition);
3675 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3677 char_length, e_text);
3680 * This condition exploits the single-matching-schema rule to
3681 * speed up the query
3683 appendPQExpBuffer(&query_buffer,
3684 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3685 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3686 char_length, e_text);
3687 appendPQExpBuffer(&query_buffer,
3688 " AND (SELECT pg_catalog.count(*)"
3689 " FROM pg_catalog.pg_namespace"
3690 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3691 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3692 char_length, e_text);
3694 /* If an addon query was provided, use it */
3695 if (completion_charp)
3696 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3700 /* completion_charp is an sprintf-style format string */
3701 appendPQExpBuffer(&query_buffer, completion_charp,
3702 char_length, e_text,
3703 e_info_charp, e_info_charp,
3704 e_info_charp2, e_info_charp2);
3707 /* Limit the number of records in the result */
3708 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3709 completion_max_records);
3711 result = exec_query(query_buffer.data);
3713 termPQExpBuffer(&query_buffer);
3718 free(e_info_charp2);
3721 /* Find something that matches */
3722 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3726 while (list_index < PQntuples(result) &&
3727 (item = PQgetvalue(result, list_index++, 0)))
3728 if (pg_strncasecmp(text, item, byte_length) == 0)
3729 return pg_strdup(item);
3732 /* If nothing matches, free the db structure and return null */
3740 * This function returns in order one of a fixed, NULL pointer terminated list
3741 * of strings (if matching). This can be used if there are only a fixed number
3742 * SQL words that can appear at certain spot.
3745 complete_from_list(const char *text, int state)
3747 static int string_length,
3750 static bool casesensitive;
3753 /* need to have a list */
3754 Assert(completion_charpp != NULL);
3756 /* Initialization */
3760 string_length = strlen(text);
3761 casesensitive = completion_case_sensitive;
3765 while ((item = completion_charpp[list_index++]))
3767 /* First pass is case sensitive */
3768 if (casesensitive && strncmp(text, item, string_length) == 0)
3771 return pg_strdup(item);
3774 /* Second pass is case insensitive, don't bother counting matches */
3775 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3777 if (completion_case_sensitive)
3778 return pg_strdup(item);
3782 * If case insensitive matching was requested initially,
3783 * adjust the case according to setting.
3785 return pg_strdup_keyword_case(item, text);
3790 * No matches found. If we're not case insensitive already, lets switch to
3791 * being case insensitive and try again
3793 if (casesensitive && matches == 0)
3795 casesensitive = false;
3798 return complete_from_list(text, state);
3801 /* If no more matches, return null. */
3807 * This function returns one fixed string the first time even if it doesn't
3808 * match what's there, and nothing the second time. This should be used if
3809 * there is only one possibility that can appear at a certain spot, so
3810 * misspellings will be overwritten. The string to be passed must be in
3814 complete_from_const(const char *text, int state)
3816 Assert(completion_charp != NULL);
3819 if (completion_case_sensitive)
3820 return pg_strdup(completion_charp);
3824 * If case insensitive matching was requested initially, adjust
3825 * the case according to setting.
3827 return pg_strdup_keyword_case(completion_charp, text);
3835 * This function appends the variable name with prefix and suffix to
3836 * the variable names array.
3839 append_variable_names(char ***varnames, int *nvars,
3840 int *maxvars, const char *varname,
3841 const char *prefix, const char *suffix)
3843 if (*nvars >= *maxvars)
3846 *varnames = (char **) pg_realloc(*varnames,
3847 ((*maxvars) + 1) * sizeof(char *));
3850 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3855 * This function supports completion with the name of a psql variable.
3856 * The variable names can be prefixed and suffixed with additional text
3857 * to support quoting usages. If need_value is true, only variables
3858 * that are currently set are included; otherwise, special variables
3859 * (those that have hooks) are included even if currently unset.
3862 complete_from_variables(const char *text, const char *prefix, const char *suffix,
3870 struct _variable *ptr;
3872 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
3874 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3876 if (need_value && !(ptr->value))
3878 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3882 varnames[nvars] = NULL;
3883 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
3885 for (i = 0; i < nvars; i++)
3894 * This function wraps rl_filename_completion_function() to strip quotes from
3895 * the input before searching for matches and to quote any matches for which
3896 * the consuming command will require it.
3899 complete_from_files(const char *text, int state)
3901 static const char *unquoted_text;
3902 char *unquoted_match;
3907 /* Initialization: stash the unquoted input. */
3908 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
3909 false, true, pset.encoding);
3910 /* expect a NULL return for the empty string only */
3913 Assert(*text == '\0');
3914 unquoted_text = text;
3918 unquoted_match = filename_completion_function(unquoted_text, state);
3922 * Caller sets completion_charp to a zero- or one-character string
3923 * containing the escape character. This is necessary since \copy has
3924 * no escape character, but every other backslash command recognizes
3925 * "\" as an escape character. Since we have only two callers, don't
3926 * bother providing a macro to simplify this.
3928 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
3929 '\'', *completion_charp, pset.encoding);
3931 free(unquoted_match);
3933 ret = unquoted_match;
3940 /* HELPER FUNCTIONS */
3944 * Make a pg_strdup copy of s and convert the case according to
3945 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
3948 pg_strdup_keyword_case(const char *s, const char *ref)
3952 unsigned char first = ref[0];
3956 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
3957 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
3958 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
3959 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
3961 for (p = ret; *p; p++)
3962 *p = pg_tolower((unsigned char) *p);
3966 for (p = ret; *p; p++)
3967 *p = pg_toupper((unsigned char) *p);
3975 * escape_string - Escape argument for use as string literal.
3977 * The returned value has to be freed.
3980 escape_string(const char *text)
3985 text_length = strlen(text);
3987 result = pg_malloc(text_length * 2 + 1);
3988 PQescapeStringConn(pset.db, result, text, text_length, NULL);
3995 * Execute a query and report any errors. This should be the preferred way of
3996 * talking to the database in this file.
3999 exec_query(const char *query)
4003 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
4006 result = PQexec(pset.db, query);
4008 if (PQresultStatus(result) != PGRES_TUPLES_OK)
4011 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
4012 PQerrorMessage(pset.db), query);
4023 * Parse all the word(s) before point.
4025 * Returns a malloc'd array of character pointers that point into the malloc'd
4026 * data array returned to *buffer; caller must free() both of these when done.
4027 * *nwords receives the number of words found, ie, the valid length of the
4030 * Words are returned right to left, that is, previous_words[0] gets the last
4031 * word before point, previous_words[1] the next-to-last, etc.
4034 get_previous_words(int point, char **buffer, int *nwords)
4036 char **previous_words;
4039 int words_found = 0;
4043 * If we have anything in tab_completion_query_buf, paste it together with
4044 * rl_line_buffer to construct the full query. Otherwise we can just use
4045 * rl_line_buffer as the input string.
4047 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
4049 i = tab_completion_query_buf->len;
4050 buf = pg_malloc(point + i + 2);
4051 memcpy(buf, tab_completion_query_buf->data, i);
4053 memcpy(buf + i, rl_line_buffer, point);
4056 /* Readjust point to reference appropriate offset in buf */
4060 buf = rl_line_buffer;
4063 * Allocate an array of string pointers and a buffer to hold the strings
4064 * themselves. The worst case is that the line contains only
4065 * non-whitespace WORD_BREAKS characters, making each one a separate word.
4066 * This is usually much more space than we need, but it's cheaper than
4067 * doing a separate malloc() for each word.
4069 previous_words = (char **) pg_malloc(point * sizeof(char *));
4070 *buffer = outptr = (char *) pg_malloc(point * 2);
4073 * First we look for a non-word char before the current point. (This is
4074 * probably useless, if readline is on the same page as we are about what
4075 * is a word, but if so it's cheap.)
4077 for (i = point - 1; i >= 0; i--)
4079 if (strchr(WORD_BREAKS, buf[i]))
4085 * Now parse words, working backwards, until we hit start of line. The
4086 * backwards scan has some interesting but intentional properties
4087 * concerning parenthesis handling.
4093 bool inquotes = false;
4094 int parentheses = 0;
4096 /* now find the first non-space which then constitutes the end */
4098 for (i = point; i >= 0; i--)
4100 if (!isspace((unsigned char) buf[i]))
4106 /* if no end found, we're done */
4111 * Otherwise we now look for the start. The start is either the last
4112 * character before any word-break character going backwards from the
4113 * end, or it's simply character 0. We also handle open quotes and
4116 for (start = end; start > 0; start--)
4118 if (buf[start] == '"')
4119 inquotes = !inquotes;
4122 if (buf[start] == ')')
4124 else if (buf[start] == '(')
4126 if (--parentheses <= 0)
4129 else if (parentheses == 0 &&
4130 strchr(WORD_BREAKS, buf[start - 1]))
4135 /* Return the word located at start to end inclusive */
4136 previous_words[words_found++] = outptr;
4137 i = end - start + 1;
4138 memcpy(outptr, &buf[start], i);
4142 /* Continue searching */
4146 /* Release parsing input workspace, if we made one above */
4147 if (buf != rl_line_buffer)
4150 *nwords = words_found;
4151 return previous_words;
4155 * Look up the type for the GUC variable with the passed name.
4157 * Returns NULL if the variable is unknown. Otherwise the returned string,
4158 * containing the type, has to be freed.
4161 get_guctype(const char *varname)
4163 PQExpBufferData query_buffer;
4166 char *guctype = NULL;
4168 e_varname = escape_string(varname);
4170 initPQExpBuffer(&query_buffer);
4171 appendPQExpBuffer(&query_buffer,
4172 "SELECT vartype FROM pg_catalog.pg_settings "
4173 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
4176 result = exec_query(query_buffer.data);
4177 termPQExpBuffer(&query_buffer);
4180 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
4181 guctype = pg_strdup(PQgetvalue(result, 0, 0));
4191 * Surround a string with single quotes. This works for both SQL and
4192 * psql internal. Currently disabled because it is reported not to
4193 * cooperate with certain versions of readline.
4196 quote_file_name(char *text, int match_type, char *quote_pointer)
4201 (void) quote_pointer; /* not used */
4203 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
4204 s = pg_malloc(length);
4206 strcpy(s + 1, text);
4207 if (match_type == SINGLE_MATCH)
4208 s[length - 2] = '\'';
4209 s[length - 1] = '\0';
4214 dequote_file_name(char *text, char quote_char)
4220 return pg_strdup(text);
4222 length = strlen(text);
4223 s = pg_malloc(length - 2 + 1);
4224 strlcpy(s, text +1, length - 2 + 1);
4228 #endif /* NOT_USED */
4230 #endif /* USE_READLINE */