2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2016, 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_FUNCTION_ARG(function) \
207 char *_completion_schema; \
208 char *_completion_function; \
210 _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
211 false, false, pset.encoding); \
212 (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
213 false, false, pset.encoding); \
214 _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
215 false, false, pset.encoding); \
216 if (_completion_function == NULL) \
218 completion_charp = Query_for_list_of_arguments; \
219 completion_info_charp = function; \
223 completion_charp = Query_for_list_of_arguments_with_schema; \
224 completion_info_charp = _completion_function; \
225 completion_info_charp2 = _completion_schema; \
227 matches = completion_matches(text, complete_from_query); \
231 * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
232 * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
234 #define COMPLETE_WITH_LIST2(s1, s2) \
236 static const char *const list[] = { s1, s2, NULL }; \
237 COMPLETE_WITH_LIST(list); \
240 #define COMPLETE_WITH_LIST3(s1, s2, s3) \
242 static const char *const list[] = { s1, s2, s3, NULL }; \
243 COMPLETE_WITH_LIST(list); \
246 #define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
248 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
249 COMPLETE_WITH_LIST(list); \
252 #define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
254 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
255 COMPLETE_WITH_LIST(list); \
258 #define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \
260 static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \
261 COMPLETE_WITH_LIST(list); \
264 #define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \
266 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \
267 COMPLETE_WITH_LIST(list); \
270 #define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \
272 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \
273 COMPLETE_WITH_LIST(list); \
276 #define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
278 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
279 COMPLETE_WITH_LIST(list); \
282 #define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
284 static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
285 COMPLETE_WITH_LIST(list); \
289 * Likewise for COMPLETE_WITH_LIST_CS.
291 #define COMPLETE_WITH_LIST_CS2(s1, s2) \
293 static const char *const list[] = { s1, s2, NULL }; \
294 COMPLETE_WITH_LIST_CS(list); \
297 #define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
299 static const char *const list[] = { s1, s2, s3, NULL }; \
300 COMPLETE_WITH_LIST_CS(list); \
303 #define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
305 static const char *const list[] = { s1, s2, s3, s4, NULL }; \
306 COMPLETE_WITH_LIST_CS(list); \
309 #define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
311 static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
312 COMPLETE_WITH_LIST_CS(list); \
316 * Assembly instructions for schema queries
319 static const SchemaQuery Query_for_list_of_aggregates = {
321 "pg_catalog.pg_proc p",
325 "pg_catalog.pg_function_is_visible(p.oid)",
329 "pg_catalog.quote_ident(p.proname)",
334 static const SchemaQuery Query_for_list_of_datatypes = {
336 "pg_catalog.pg_type t",
337 /* selcondition --- ignore table rowtypes and array types */
339 " OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
340 "AND t.typname !~ '^_'",
342 "pg_catalog.pg_type_is_visible(t.oid)",
346 "pg_catalog.format_type(t.oid, NULL)",
348 "pg_catalog.quote_ident(t.typname)"
351 static const SchemaQuery Query_for_list_of_domains = {
353 "pg_catalog.pg_type t",
357 "pg_catalog.pg_type_is_visible(t.oid)",
361 "pg_catalog.quote_ident(t.typname)",
366 static const SchemaQuery Query_for_list_of_functions = {
368 "pg_catalog.pg_proc p",
372 "pg_catalog.pg_function_is_visible(p.oid)",
376 "pg_catalog.quote_ident(p.proname)",
381 static const SchemaQuery Query_for_list_of_indexes = {
383 "pg_catalog.pg_class c",
385 "c.relkind IN ('i')",
387 "pg_catalog.pg_table_is_visible(c.oid)",
391 "pg_catalog.quote_ident(c.relname)",
396 static const SchemaQuery Query_for_list_of_sequences = {
398 "pg_catalog.pg_class c",
400 "c.relkind IN ('S')",
402 "pg_catalog.pg_table_is_visible(c.oid)",
406 "pg_catalog.quote_ident(c.relname)",
411 static const SchemaQuery Query_for_list_of_foreign_tables = {
413 "pg_catalog.pg_class c",
415 "c.relkind IN ('f')",
417 "pg_catalog.pg_table_is_visible(c.oid)",
421 "pg_catalog.quote_ident(c.relname)",
426 static const SchemaQuery Query_for_list_of_tables = {
428 "pg_catalog.pg_class c",
430 "c.relkind IN ('r')",
432 "pg_catalog.pg_table_is_visible(c.oid)",
436 "pg_catalog.quote_ident(c.relname)",
441 static const SchemaQuery Query_for_list_of_constraints_with_schema = {
443 "pg_catalog.pg_constraint c",
447 "true", /* there is no pg_constraint_is_visible */
451 "pg_catalog.quote_ident(c.conname)",
456 /* Relations supporting INSERT, UPDATE or DELETE */
457 static const SchemaQuery Query_for_list_of_updatables = {
459 "pg_catalog.pg_class c",
461 "c.relkind IN ('r', 'f', 'v')",
463 "pg_catalog.pg_table_is_visible(c.oid)",
467 "pg_catalog.quote_ident(c.relname)",
472 static const SchemaQuery Query_for_list_of_relations = {
474 "pg_catalog.pg_class c",
478 "pg_catalog.pg_table_is_visible(c.oid)",
482 "pg_catalog.quote_ident(c.relname)",
487 static const SchemaQuery Query_for_list_of_tsvmf = {
489 "pg_catalog.pg_class c",
491 "c.relkind IN ('r', 'S', 'v', 'm', 'f')",
493 "pg_catalog.pg_table_is_visible(c.oid)",
497 "pg_catalog.quote_ident(c.relname)",
502 static const SchemaQuery Query_for_list_of_tmf = {
504 "pg_catalog.pg_class c",
506 "c.relkind IN ('r', 'm', 'f')",
508 "pg_catalog.pg_table_is_visible(c.oid)",
512 "pg_catalog.quote_ident(c.relname)",
517 static const SchemaQuery Query_for_list_of_tm = {
519 "pg_catalog.pg_class c",
521 "c.relkind IN ('r', 'm')",
523 "pg_catalog.pg_table_is_visible(c.oid)",
527 "pg_catalog.quote_ident(c.relname)",
532 static const SchemaQuery Query_for_list_of_views = {
534 "pg_catalog.pg_class c",
536 "c.relkind IN ('v')",
538 "pg_catalog.pg_table_is_visible(c.oid)",
542 "pg_catalog.quote_ident(c.relname)",
547 static const SchemaQuery Query_for_list_of_matviews = {
549 "pg_catalog.pg_class c",
551 "c.relkind IN ('m')",
553 "pg_catalog.pg_table_is_visible(c.oid)",
557 "pg_catalog.quote_ident(c.relname)",
564 * Queries to get lists of names of various kinds of things, possibly
565 * restricted to names matching a partially entered name. In these queries,
566 * the first %s will be replaced by the text entered so far (suitably escaped
567 * to become a SQL literal string). %d will be replaced by the length of the
568 * string (in unescaped form). A second and third %s, if present, will be
569 * replaced by a suitably-escaped version of the string provided in
570 * completion_info_charp. A fourth and fifth %s are similarly replaced by
571 * completion_info_charp2.
573 * Beware that the allowed sequences of %s and %d are determined by
574 * _complete_from_query().
577 #define Query_for_list_of_attributes \
578 "SELECT pg_catalog.quote_ident(attname) "\
579 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
580 " WHERE c.oid = a.attrelid "\
581 " AND a.attnum > 0 "\
582 " AND NOT a.attisdropped "\
583 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
584 " AND (pg_catalog.quote_ident(relname)='%s' "\
585 " OR '\"' || relname || '\"'='%s') "\
586 " AND pg_catalog.pg_table_is_visible(c.oid)"
588 #define Query_for_list_of_attributes_with_schema \
589 "SELECT pg_catalog.quote_ident(attname) "\
590 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
591 " WHERE c.oid = a.attrelid "\
592 " AND n.oid = c.relnamespace "\
593 " AND a.attnum > 0 "\
594 " AND NOT a.attisdropped "\
595 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
596 " AND (pg_catalog.quote_ident(relname)='%s' "\
597 " OR '\"' || relname || '\"' ='%s') "\
598 " AND (pg_catalog.quote_ident(nspname)='%s' "\
599 " OR '\"' || nspname || '\"' ='%s') "
601 #define Query_for_list_of_template_databases \
602 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
603 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s' AND datistemplate"
605 #define Query_for_list_of_databases \
606 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
607 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
609 #define Query_for_list_of_tablespaces \
610 "SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\
611 " WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'"
613 #define Query_for_list_of_encodings \
614 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
615 " FROM pg_catalog.pg_conversion "\
616 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
618 #define Query_for_list_of_languages \
619 "SELECT pg_catalog.quote_ident(lanname) "\
620 " FROM pg_catalog.pg_language "\
621 " WHERE lanname != 'internal' "\
622 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'"
624 #define Query_for_list_of_schemas \
625 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
626 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
628 #define Query_for_list_of_alter_system_set_vars \
630 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
631 " WHERE context != 'internal') ss "\
632 " WHERE substring(name,1,%d)='%s'"\
633 " UNION ALL SELECT 'all' ss"
635 #define Query_for_list_of_set_vars \
637 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
638 " WHERE context IN ('user', 'superuser') "\
639 " UNION ALL SELECT 'constraints' "\
640 " UNION ALL SELECT 'transaction' "\
641 " UNION ALL SELECT 'session' "\
642 " UNION ALL SELECT 'role' "\
643 " UNION ALL SELECT 'tablespace' "\
644 " UNION ALL SELECT 'all') ss "\
645 " WHERE substring(name,1,%d)='%s'"
647 #define Query_for_list_of_show_vars \
649 " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
650 " UNION ALL SELECT 'session authorization' "\
651 " UNION ALL SELECT 'all') ss "\
652 " WHERE substring(name,1,%d)='%s'"
654 #define Query_for_list_of_roles \
655 " SELECT pg_catalog.quote_ident(rolname) "\
656 " FROM pg_catalog.pg_roles "\
657 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
659 #define Query_for_list_of_grant_roles \
660 " SELECT pg_catalog.quote_ident(rolname) "\
661 " FROM pg_catalog.pg_roles "\
662 " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
663 " UNION ALL SELECT 'PUBLIC'"\
664 " UNION ALL SELECT 'CURRENT_USER'"\
665 " UNION ALL SELECT 'SESSION_USER'"
667 /* the silly-looking length condition is just to eat up the current word */
668 #define Query_for_table_owning_index \
669 "SELECT pg_catalog.quote_ident(c1.relname) "\
670 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
671 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
672 " and (%d = pg_catalog.length('%s'))"\
673 " and pg_catalog.quote_ident(c2.relname)='%s'"\
674 " and pg_catalog.pg_table_is_visible(c2.oid)"
676 /* the silly-looking length condition is just to eat up the current word */
677 #define Query_for_index_of_table \
678 "SELECT pg_catalog.quote_ident(c2.relname) "\
679 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
680 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
681 " and (%d = pg_catalog.length('%s'))"\
682 " and pg_catalog.quote_ident(c1.relname)='%s'"\
683 " and pg_catalog.pg_table_is_visible(c2.oid)"
685 /* the silly-looking length condition is just to eat up the current word */
686 #define Query_for_constraint_of_table \
687 "SELECT pg_catalog.quote_ident(conname) "\
688 " FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\
689 " WHERE c1.oid=conrelid and (%d = pg_catalog.length('%s'))"\
690 " and pg_catalog.quote_ident(c1.relname)='%s'"\
691 " and pg_catalog.pg_table_is_visible(c1.oid)"
693 #define Query_for_all_table_constraints \
694 "SELECT pg_catalog.quote_ident(conname) "\
695 " FROM pg_catalog.pg_constraint c "\
696 " WHERE c.conrelid <> 0 "
698 /* the silly-looking length condition is just to eat up the current word */
699 #define Query_for_constraint_of_type \
700 "SELECT pg_catalog.quote_ident(conname) "\
701 " FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\
702 " WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\
703 " and pg_catalog.quote_ident(t.typname)='%s'"\
704 " and pg_catalog.pg_type_is_visible(t.oid)"
706 /* the silly-looking length condition is just to eat up the current word */
707 #define Query_for_list_of_tables_for_constraint \
708 "SELECT pg_catalog.quote_ident(relname) "\
709 " FROM pg_catalog.pg_class"\
710 " WHERE (%d = pg_catalog.length('%s'))"\
712 " (SELECT conrelid FROM pg_catalog.pg_constraint "\
713 " WHERE pg_catalog.quote_ident(conname)='%s')"
715 /* the silly-looking length condition is just to eat up the current word */
716 #define Query_for_rule_of_table \
717 "SELECT pg_catalog.quote_ident(rulename) "\
718 " FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
719 " WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
720 " and pg_catalog.quote_ident(c1.relname)='%s'"\
721 " and pg_catalog.pg_table_is_visible(c1.oid)"
723 /* the silly-looking length condition is just to eat up the current word */
724 #define Query_for_list_of_tables_for_rule \
725 "SELECT pg_catalog.quote_ident(relname) "\
726 " FROM pg_catalog.pg_class"\
727 " WHERE (%d = pg_catalog.length('%s'))"\
729 " (SELECT ev_class FROM pg_catalog.pg_rewrite "\
730 " WHERE pg_catalog.quote_ident(rulename)='%s')"
732 /* the silly-looking length condition is just to eat up the current word */
733 #define Query_for_trigger_of_table \
734 "SELECT pg_catalog.quote_ident(tgname) "\
735 " FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
736 " WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
737 " and pg_catalog.quote_ident(c1.relname)='%s'"\
738 " and pg_catalog.pg_table_is_visible(c1.oid)"\
739 " and not tgisinternal"
741 /* the silly-looking length condition is just to eat up the current word */
742 #define Query_for_list_of_tables_for_trigger \
743 "SELECT pg_catalog.quote_ident(relname) "\
744 " FROM pg_catalog.pg_class"\
745 " WHERE (%d = pg_catalog.length('%s'))"\
747 " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
748 " WHERE pg_catalog.quote_ident(tgname)='%s')"
750 #define Query_for_list_of_ts_configurations \
751 "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\
752 " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'"
754 #define Query_for_list_of_ts_dictionaries \
755 "SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\
756 " WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'"
758 #define Query_for_list_of_ts_parsers \
759 "SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\
760 " WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'"
762 #define Query_for_list_of_ts_templates \
763 "SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
764 " WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
766 #define Query_for_list_of_fdws \
767 " SELECT pg_catalog.quote_ident(fdwname) "\
768 " FROM pg_catalog.pg_foreign_data_wrapper "\
769 " WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
771 #define Query_for_list_of_servers \
772 " SELECT pg_catalog.quote_ident(srvname) "\
773 " FROM pg_catalog.pg_foreign_server "\
774 " WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
776 #define Query_for_list_of_user_mappings \
777 " SELECT pg_catalog.quote_ident(usename) "\
778 " FROM pg_catalog.pg_user_mappings "\
779 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
781 #define Query_for_list_of_access_methods \
782 " SELECT pg_catalog.quote_ident(amname) "\
783 " FROM pg_catalog.pg_am "\
784 " WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'"
786 /* the silly-looking length condition is just to eat up the current word */
787 #define Query_for_list_of_arguments \
788 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
789 " FROM pg_catalog.pg_proc "\
790 " WHERE (%d = pg_catalog.length('%s'))"\
791 " AND (pg_catalog.quote_ident(proname)='%s'"\
792 " OR '\"' || proname || '\"'='%s') "\
793 " AND (pg_catalog.pg_function_is_visible(pg_proc.oid))"
795 /* the silly-looking length condition is just to eat up the current word */
796 #define Query_for_list_of_arguments_with_schema \
797 "SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\
798 " FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\
799 " WHERE (%d = pg_catalog.length('%s'))"\
800 " AND n.oid = p.pronamespace "\
801 " AND (pg_catalog.quote_ident(proname)='%s' "\
802 " OR '\"' || proname || '\"' ='%s') "\
803 " AND (pg_catalog.quote_ident(nspname)='%s' "\
804 " OR '\"' || nspname || '\"' ='%s') "
806 #define Query_for_list_of_extensions \
807 " SELECT pg_catalog.quote_ident(extname) "\
808 " FROM pg_catalog.pg_extension "\
809 " WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'"
811 #define Query_for_list_of_available_extensions \
812 " SELECT pg_catalog.quote_ident(name) "\
813 " FROM pg_catalog.pg_available_extensions "\
814 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL"
816 /* the silly-looking length condition is just to eat up the current word */
817 #define Query_for_list_of_available_extension_versions \
818 " SELECT pg_catalog.quote_ident(version) "\
819 " FROM pg_catalog.pg_available_extension_versions "\
820 " WHERE (%d = pg_catalog.length('%s'))"\
821 " AND pg_catalog.quote_ident(name)='%s'"
823 #define Query_for_list_of_prepared_statements \
824 " SELECT pg_catalog.quote_ident(name) "\
825 " FROM pg_catalog.pg_prepared_statements "\
826 " WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'"
828 #define Query_for_list_of_event_triggers \
829 " SELECT pg_catalog.quote_ident(evtname) "\
830 " FROM pg_catalog.pg_event_trigger "\
831 " WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'"
833 #define Query_for_list_of_tablesample_methods \
834 " SELECT pg_catalog.quote_ident(proname) "\
835 " FROM pg_catalog.pg_proc "\
836 " WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\
837 " proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\
838 " substring(pg_catalog.quote_ident(proname),1,%d)='%s'"
840 #define Query_for_list_of_policies \
841 " SELECT pg_catalog.quote_ident(polname) "\
842 " FROM pg_catalog.pg_policy "\
843 " WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'"
845 #define Query_for_list_of_tables_for_policy \
846 "SELECT pg_catalog.quote_ident(relname) "\
847 " FROM pg_catalog.pg_class"\
848 " WHERE (%d = pg_catalog.length('%s'))"\
850 " (SELECT polrelid FROM pg_catalog.pg_policy "\
851 " WHERE pg_catalog.quote_ident(polname)='%s')"
853 #define Query_for_enum \
854 " SELECT name FROM ( "\
855 " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
856 " FROM pg_catalog.pg_settings "\
857 " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
859 " SELECT 'DEFAULT' ) ss "\
860 " WHERE pg_catalog.substring(name,1,%%d)='%%s'"
863 * This is a list of all "things" in Pgsql, which can show up after CREATE or
864 * DROP; and there is also a query to get a list of them.
870 const char *query; /* simple query, or NULL */
871 const SchemaQuery *squery; /* schema query, or NULL */
872 const bits32 flags; /* visibility flags, see below */
875 #define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
876 #define THING_NO_DROP (1 << 1) /* should not show up after DROP */
877 #define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP)
879 static const pgsql_thing_t words_after_create[] = {
880 {"ACCESS METHOD", NULL, NULL},
881 {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
882 {"CAST", NULL, NULL}, /* Casts have complex structures for names, so
884 {"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'"},
887 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
888 * to be used only by pg_dump.
890 {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
891 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
892 {"DATABASE", Query_for_list_of_databases},
893 {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
894 {"DOMAIN", NULL, &Query_for_list_of_domains},
895 {"EVENT TRIGGER", NULL, NULL},
896 {"EXTENSION", Query_for_list_of_extensions},
897 {"FOREIGN DATA WRAPPER", NULL, NULL},
898 {"FOREIGN TABLE", NULL, NULL},
899 {"FUNCTION", NULL, &Query_for_list_of_functions},
900 {"GROUP", Query_for_list_of_roles},
901 {"LANGUAGE", Query_for_list_of_languages},
902 {"INDEX", NULL, &Query_for_list_of_indexes},
903 {"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
904 {"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a
906 {"OWNED", NULL, NULL, THING_NO_CREATE}, /* for DROP OWNED BY ... */
907 {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
908 {"POLICY", NULL, NULL},
909 {"ROLE", Query_for_list_of_roles},
910 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
911 {"SCHEMA", Query_for_list_of_schemas},
912 {"SEQUENCE", NULL, &Query_for_list_of_sequences},
913 {"SERVER", Query_for_list_of_servers},
914 {"TABLE", NULL, &Query_for_list_of_tables},
915 {"TABLESPACE", Query_for_list_of_tablespaces},
916 {"TEMP", NULL, NULL, THING_NO_DROP}, /* for CREATE TEMP TABLE ... */
917 {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
918 {"TEXT SEARCH", NULL, NULL},
919 {"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"},
920 {"TYPE", NULL, &Query_for_list_of_datatypes},
921 {"UNIQUE", NULL, NULL, THING_NO_DROP}, /* for CREATE UNIQUE INDEX ... */
922 {"UNLOGGED", NULL, NULL, THING_NO_DROP}, /* for CREATE UNLOGGED TABLE
924 {"USER", Query_for_list_of_roles},
925 {"USER MAPPING FOR", NULL, NULL},
926 {"VIEW", NULL, &Query_for_list_of_views},
927 {NULL} /* end of list */
931 /* Forward declaration of functions */
932 static char **psql_completion(const char *text, int start, int end);
933 static char *create_command_generator(const char *text, int state);
934 static char *drop_command_generator(const char *text, int state);
935 static char *complete_from_query(const char *text, int state);
936 static char *complete_from_schema_query(const char *text, int state);
937 static char *_complete_from_query(int is_schema_query,
938 const char *text, int state);
939 static char *complete_from_list(const char *text, int state);
940 static char *complete_from_const(const char *text, int state);
941 static void append_variable_names(char ***varnames, int *nvars,
942 int *maxvars, const char *varname,
943 const char *prefix, const char *suffix);
944 static char **complete_from_variables(const char *text,
945 const char *prefix, const char *suffix, bool need_value);
946 static char *complete_from_files(const char *text, int state);
948 static char *pg_strdup_keyword_case(const char *s, const char *ref);
949 static char *escape_string(const char *text);
950 static PGresult *exec_query(const char *query);
952 static char **get_previous_words(int point, char **buffer, int *nwords);
954 static char *get_guctype(const char *varname);
957 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
958 static char *dequote_file_name(char *text, char quote_char);
963 * Initialize the readline library for our purposes.
966 initialize_readline(void)
968 rl_readline_name = (char *) pset.progname;
969 rl_attempted_completion_function = psql_completion;
971 rl_basic_word_break_characters = WORD_BREAKS;
973 completion_max_records = 1000;
976 * There is a variable rl_completion_query_items for this but apparently
977 * it's not defined everywhere.
982 * Check if 'word' matches any of the '|'-separated strings in 'pattern',
983 * using case-insensitive or case-sensitive comparisons.
985 * If pattern is NULL, it's a wild card that matches any word.
986 * If pattern begins with '!', the result is negated, ie we check that 'word'
987 * does *not* match any alternative appearing in the rest of 'pattern'.
988 * Any alternative can end with '*' which is a wild card, i.e., it means
989 * match any word that matches the characters so far. (We do not currently
990 * support '*' elsewhere than the end of an alternative.)
992 * For readability, callers should use the macros MatchAny and MatchAnyExcept
993 * to invoke those two special cases for 'pattern'. (But '|' and '*' must
994 * just be written directly in patterns.)
996 #define MatchAny NULL
997 #define MatchAnyExcept(pattern) ("!" pattern)
1000 word_matches_internal(const char *pattern,
1002 bool case_sensitive)
1007 /* NULL pattern matches anything. */
1008 if (pattern == NULL)
1011 /* Handle negated patterns from the MatchAnyExcept macro. */
1012 if (*pattern == '!')
1013 return !word_matches_internal(pattern + 1, word, case_sensitive);
1015 /* Else consider each alternative in the pattern. */
1016 wordlen = strlen(word);
1021 /* Find end of current alternative. */
1023 while (*c != '\0' && *c != '|')
1025 /* Was there a wild card? (Assumes first alternative is not empty) */
1028 /* Yes, wildcard match? */
1029 patternlen = c - pattern - 1;
1030 if (wordlen >= patternlen &&
1032 strncmp(word, pattern, patternlen) == 0 :
1033 pg_strncasecmp(word, pattern, patternlen) == 0))
1038 /* No, plain match? */
1039 patternlen = c - pattern;
1040 if (wordlen == patternlen &&
1042 strncmp(word, pattern, wordlen) == 0 :
1043 pg_strncasecmp(word, pattern, wordlen) == 0))
1046 /* Out of alternatives? */
1049 /* Nope, try next alternative. */
1057 * There are enough matching calls below that it seems worth having these two
1058 * interface routines rather than including a third parameter in every call.
1060 * word_matches --- match case-insensitively.
1063 word_matches(const char *pattern, const char *word)
1065 return word_matches_internal(pattern, word, false);
1069 * word_matches_cs --- match case-sensitively.
1072 word_matches_cs(const char *pattern, const char *word)
1074 return word_matches_internal(pattern, word, true);
1078 * Check if the final character of 's' is 'c'.
1081 ends_with(const char *s, char c)
1083 size_t length = strlen(s);
1085 return (length > 0 && s[length - 1] == c);
1089 * The completion function.
1091 * According to readline spec this gets passed the text entered so far and its
1092 * start and end positions in the readline buffer. The return value is some
1093 * partially obscure list format that can be generated by readline's
1094 * completion_matches() function, so we don't have to worry about it.
1097 psql_completion(const char *text, int start, int end)
1099 /* This is the variable we'll return. */
1100 char **matches = NULL;
1102 /* Workspace for parsed words. */
1105 /* This array will contain pointers to parsed words. */
1106 char **previous_words;
1108 /* The number of words found on the input line. */
1109 int previous_words_count;
1112 * For compactness, we use these macros to reference previous_words[].
1113 * Caution: do not access a previous_words[] entry without having checked
1114 * previous_words_count to be sure it's valid. In most cases below, that
1115 * check is implicit in a TailMatches() or similar macro, but in some
1116 * places we have to check it explicitly.
1118 #define prev_wd (previous_words[0])
1119 #define prev2_wd (previous_words[1])
1120 #define prev3_wd (previous_words[2])
1121 #define prev4_wd (previous_words[3])
1122 #define prev5_wd (previous_words[4])
1123 #define prev6_wd (previous_words[5])
1124 #define prev7_wd (previous_words[6])
1125 #define prev8_wd (previous_words[7])
1126 #define prev9_wd (previous_words[8])
1128 /* Macros for matching the last N words before point, case-insensitively. */
1129 #define TailMatches1(p1) \
1130 (previous_words_count >= 1 && \
1131 word_matches(p1, prev_wd))
1133 #define TailMatches2(p2, p1) \
1134 (previous_words_count >= 2 && \
1135 word_matches(p1, prev_wd) && \
1136 word_matches(p2, prev2_wd))
1138 #define TailMatches3(p3, p2, p1) \
1139 (previous_words_count >= 3 && \
1140 word_matches(p1, prev_wd) && \
1141 word_matches(p2, prev2_wd) && \
1142 word_matches(p3, prev3_wd))
1144 #define TailMatches4(p4, p3, p2, p1) \
1145 (previous_words_count >= 4 && \
1146 word_matches(p1, prev_wd) && \
1147 word_matches(p2, prev2_wd) && \
1148 word_matches(p3, prev3_wd) && \
1149 word_matches(p4, prev4_wd))
1151 #define TailMatches5(p5, p4, p3, p2, p1) \
1152 (previous_words_count >= 5 && \
1153 word_matches(p1, prev_wd) && \
1154 word_matches(p2, prev2_wd) && \
1155 word_matches(p3, prev3_wd) && \
1156 word_matches(p4, prev4_wd) && \
1157 word_matches(p5, prev5_wd))
1159 #define TailMatches6(p6, p5, p4, p3, p2, p1) \
1160 (previous_words_count >= 6 && \
1161 word_matches(p1, prev_wd) && \
1162 word_matches(p2, prev2_wd) && \
1163 word_matches(p3, prev3_wd) && \
1164 word_matches(p4, prev4_wd) && \
1165 word_matches(p5, prev5_wd) && \
1166 word_matches(p6, prev6_wd))
1168 #define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
1169 (previous_words_count >= 7 && \
1170 word_matches(p1, prev_wd) && \
1171 word_matches(p2, prev2_wd) && \
1172 word_matches(p3, prev3_wd) && \
1173 word_matches(p4, prev4_wd) && \
1174 word_matches(p5, prev5_wd) && \
1175 word_matches(p6, prev6_wd) && \
1176 word_matches(p7, prev7_wd))
1178 #define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
1179 (previous_words_count >= 8 && \
1180 word_matches(p1, prev_wd) && \
1181 word_matches(p2, prev2_wd) && \
1182 word_matches(p3, prev3_wd) && \
1183 word_matches(p4, prev4_wd) && \
1184 word_matches(p5, prev5_wd) && \
1185 word_matches(p6, prev6_wd) && \
1186 word_matches(p7, prev7_wd) && \
1187 word_matches(p8, prev8_wd))
1189 #define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
1190 (previous_words_count >= 9 && \
1191 word_matches(p1, prev_wd) && \
1192 word_matches(p2, prev2_wd) && \
1193 word_matches(p3, prev3_wd) && \
1194 word_matches(p4, prev4_wd) && \
1195 word_matches(p5, prev5_wd) && \
1196 word_matches(p6, prev6_wd) && \
1197 word_matches(p7, prev7_wd) && \
1198 word_matches(p8, prev8_wd) && \
1199 word_matches(p9, prev9_wd))
1201 /* Macros for matching the last N words before point, case-sensitively. */
1202 #define TailMatchesCS1(p1) \
1203 (previous_words_count >= 1 && \
1204 word_matches_cs(p1, prev_wd))
1205 #define TailMatchesCS2(p2, p1) \
1206 (previous_words_count >= 2 && \
1207 word_matches_cs(p1, prev_wd) && \
1208 word_matches_cs(p2, prev2_wd))
1211 * Macros for matching N words beginning at the start of the line,
1212 * case-insensitively.
1214 #define Matches1(p1) \
1215 (previous_words_count == 1 && \
1217 #define Matches2(p1, p2) \
1218 (previous_words_count == 2 && \
1219 TailMatches2(p1, p2))
1220 #define Matches3(p1, p2, p3) \
1221 (previous_words_count == 3 && \
1222 TailMatches3(p1, p2, p3))
1223 #define Matches4(p1, p2, p3, p4) \
1224 (previous_words_count == 4 && \
1225 TailMatches4(p1, p2, p3, p4))
1226 #define Matches5(p1, p2, p3, p4, p5) \
1227 (previous_words_count == 5 && \
1228 TailMatches5(p1, p2, p3, p4, p5))
1229 #define Matches6(p1, p2, p3, p4, p5, p6) \
1230 (previous_words_count == 6 && \
1231 TailMatches6(p1, p2, p3, p4, p5, p6))
1232 #define Matches7(p1, p2, p3, p4, p5, p6, p7) \
1233 (previous_words_count == 7 && \
1234 TailMatches7(p1, p2, p3, p4, p5, p6, p7))
1235 #define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
1236 (previous_words_count == 8 && \
1237 TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
1238 #define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
1239 (previous_words_count == 9 && \
1240 TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
1243 * Macros for matching N words at the start of the line, regardless of
1244 * what is after them, case-insensitively.
1246 #define HeadMatches1(p1) \
1247 (previous_words_count >= 1 && \
1248 word_matches(p1, previous_words[previous_words_count - 1]))
1250 #define HeadMatches2(p1, p2) \
1251 (previous_words_count >= 2 && \
1252 word_matches(p1, previous_words[previous_words_count - 1]) && \
1253 word_matches(p2, previous_words[previous_words_count - 2]))
1255 #define HeadMatches3(p1, p2, p3) \
1256 (previous_words_count >= 3 && \
1257 word_matches(p1, previous_words[previous_words_count - 1]) && \
1258 word_matches(p2, previous_words[previous_words_count - 2]) && \
1259 word_matches(p3, previous_words[previous_words_count - 3]))
1261 /* Known command-starting keywords. */
1262 static const char *const sql_commands[] = {
1263 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
1264 "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
1265 "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN",
1266 "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK",
1267 "MOVE", "NOTIFY", "PREPARE",
1268 "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
1269 "RESET", "REVOKE", "ROLLBACK",
1270 "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
1271 "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH",
1275 /* psql's backslash commands. */
1276 static const char *const backslash_commands[] = {
1277 "\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy", "\\copyright",
1278 "\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1279 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1280 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1281 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
1282 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1283 "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
1284 "\\f", "\\g", "\\gexec", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
1285 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1286 "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
1287 "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t", "\\T",
1288 "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL
1291 (void) end; /* "end" is not used */
1293 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1294 rl_completion_append_character = ' ';
1297 /* Clear a few things. */
1298 completion_charp = NULL;
1299 completion_charpp = NULL;
1300 completion_info_charp = NULL;
1301 completion_info_charp2 = NULL;
1304 * Scan the input line to extract the words before our current position.
1305 * According to those we'll make some smart decisions on what the user is
1306 * probably intending to type.
1308 previous_words = get_previous_words(start,
1310 &previous_words_count);
1312 /* If current word is a backslash command, offer completions for that */
1313 if (text[0] == '\\')
1314 COMPLETE_WITH_LIST_CS(backslash_commands);
1316 /* If current word is a variable interpolation, handle that case */
1317 else if (text[0] == ':' && text[1] != ':')
1319 if (text[1] == '\'')
1320 matches = complete_from_variables(text, ":'", "'", true);
1321 else if (text[1] == '"')
1322 matches = complete_from_variables(text, ":\"", "\"", true);
1324 matches = complete_from_variables(text, ":", "", true);
1327 /* If no previous word, suggest one of the basic sql commands */
1328 else if (previous_words_count == 0)
1329 COMPLETE_WITH_LIST(sql_commands);
1332 /* complete with something you can create */
1333 else if (TailMatches1("CREATE"))
1334 matches = completion_matches(text, create_command_generator);
1336 /* DROP, but not DROP embedded in other commands */
1337 /* complete with something you can drop */
1338 else if (Matches1("DROP"))
1339 matches = completion_matches(text, drop_command_generator);
1344 else if (Matches2("ALTER", "TABLE"))
1345 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1346 "UNION SELECT 'ALL IN TABLESPACE'");
1348 /* ALTER something */
1349 else if (Matches1("ALTER"))
1351 static const char *const list_ALTER[] =
1352 {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
1353 "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
1354 "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR",
1355 "POLICY", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM", "TABLE",
1356 "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
1357 "USER", "USER MAPPING FOR", "VIEW", NULL};
1359 COMPLETE_WITH_LIST(list_ALTER);
1361 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1362 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1363 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1364 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1365 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1366 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1367 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1368 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1369 COMPLETE_WITH_CONST("SET TABLESPACE");
1370 /* ALTER AGGREGATE,FUNCTION <name> */
1371 else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1372 COMPLETE_WITH_CONST("(");
1373 /* ALTER AGGREGATE,FUNCTION <name> (...) */
1374 else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1376 if (ends_with(prev_wd, ')'))
1377 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1379 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1382 /* ALTER SCHEMA <name> */
1383 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1384 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1386 /* ALTER COLLATION <name> */
1387 else if (Matches3("ALTER", "COLLATION", MatchAny))
1388 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1390 /* ALTER CONVERSION <name> */
1391 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1392 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1394 /* ALTER DATABASE <name> */
1395 else if (Matches3("ALTER", "DATABASE", MatchAny))
1396 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1397 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1398 "CONNECTION LIMIT");
1400 /* ALTER EVENT TRIGGER */
1401 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1402 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1404 /* ALTER EVENT TRIGGER <name> */
1405 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1406 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1408 /* ALTER EVENT TRIGGER <name> ENABLE */
1409 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1410 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1412 /* ALTER EXTENSION <name> */
1413 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1414 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1417 else if (Matches2("ALTER", "FOREIGN"))
1418 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1420 /* ALTER FOREIGN DATA WRAPPER <name> */
1421 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1422 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1424 /* ALTER FOREIGN TABLE <name> */
1425 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1427 static const char *const list_ALTER_FOREIGN_TABLE[] =
1428 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1429 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1430 "VALIDATE CONSTRAINT", NULL};
1432 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1436 else if (Matches2("ALTER", "INDEX"))
1437 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1438 "UNION SELECT 'ALL IN TABLESPACE'");
1439 /* ALTER INDEX <name> */
1440 else if (Matches3("ALTER", "INDEX", MatchAny))
1441 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1442 /* ALTER INDEX <name> SET */
1443 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1444 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1445 /* ALTER INDEX <name> RESET */
1446 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1447 COMPLETE_WITH_CONST("(");
1448 /* ALTER INDEX <foo> SET|RESET ( */
1449 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1450 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1451 "gin_pending_list_limit");
1452 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1453 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1454 "gin_pending_list_limit =");
1456 /* ALTER LANGUAGE <name> */
1457 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1458 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1460 /* ALTER LARGE OBJECT <oid> */
1461 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1462 COMPLETE_WITH_CONST("OWNER TO");
1464 /* ALTER MATERIALIZED VIEW */
1465 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1466 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1467 "UNION SELECT 'ALL IN TABLESPACE'");
1469 /* ALTER USER,ROLE <name> */
1470 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1471 !TailMatches2("USER", "MAPPING"))
1473 static const char *const list_ALTERUSER[] =
1474 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1475 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1476 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1477 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1478 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1479 "VALID UNTIL", "WITH", NULL};
1481 COMPLETE_WITH_LIST(list_ALTERUSER);
1484 /* ALTER USER,ROLE <name> WITH */
1485 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1487 /* Similar to the above, but don't complete "WITH" again. */
1488 static const char *const list_ALTERUSER_WITH[] =
1489 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1490 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1491 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1492 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1493 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1494 "VALID UNTIL", NULL};
1496 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1499 /* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
1500 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
1501 COMPLETE_WITH_CONST("PASSWORD");
1502 /* ALTER DEFAULT PRIVILEGES */
1503 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1504 COMPLETE_WITH_LIST3("FOR ROLE", "FOR USER", "IN SCHEMA");
1505 /* ALTER DEFAULT PRIVILEGES FOR */
1506 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1507 COMPLETE_WITH_LIST2("ROLE", "USER");
1508 /* ALTER DEFAULT PRIVILEGES { FOR ROLE ... | IN SCHEMA ... } */
1509 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER", MatchAny) ||
1510 Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA", MatchAny))
1511 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1512 /* ALTER DOMAIN <name> */
1513 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1514 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1515 "VALIDATE CONSTRAINT");
1516 /* ALTER DOMAIN <sth> DROP */
1517 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1518 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1519 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1520 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1522 completion_info_charp = prev3_wd;
1523 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1525 /* ALTER DOMAIN <sth> RENAME */
1526 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1527 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1528 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1529 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1530 COMPLETE_WITH_CONST("TO");
1532 /* ALTER DOMAIN <sth> SET */
1533 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1534 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1535 /* ALTER SEQUENCE <name> */
1536 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1538 static const char *const list_ALTERSEQUENCE[] =
1539 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1540 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1542 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1544 /* ALTER SEQUENCE <name> NO */
1545 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1546 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1547 /* ALTER SERVER <name> */
1548 else if (Matches3("ALTER", "SERVER", MatchAny))
1549 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1550 /* ALTER SERVER <name> VERSION <version>*/
1551 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1552 COMPLETE_WITH_CONST("OPTIONS");
1553 /* ALTER SYSTEM SET, RESET, RESET ALL */
1554 else if (Matches2("ALTER", "SYSTEM"))
1555 COMPLETE_WITH_LIST2("SET", "RESET");
1556 /* ALTER SYSTEM SET|RESET <name> */
1557 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1558 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1559 /* ALTER VIEW <name> */
1560 else if (Matches3("ALTER", "VIEW", MatchAny))
1561 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1563 /* ALTER MATERIALIZED VIEW <name> */
1564 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1565 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1568 /* ALTER POLICY <name> */
1569 else if (Matches2("ALTER", "POLICY"))
1570 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1571 /* ALTER POLICY <name> ON */
1572 else if (Matches3("ALTER", "POLICY", MatchAny))
1573 COMPLETE_WITH_CONST("ON");
1574 /* ALTER POLICY <name> ON <table> */
1575 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1577 completion_info_charp = prev2_wd;
1578 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1580 /* ALTER POLICY <name> ON <table> - show options */
1581 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1582 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1583 /* ALTER POLICY <name> ON <table> TO <role> */
1584 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1585 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1586 /* ALTER POLICY <name> ON <table> USING ( */
1587 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1588 COMPLETE_WITH_CONST("(");
1589 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1590 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1591 COMPLETE_WITH_CONST("(");
1593 /* ALTER RULE <name>, add ON */
1594 else if (Matches3("ALTER", "RULE", MatchAny))
1595 COMPLETE_WITH_CONST("ON");
1597 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1598 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1600 completion_info_charp = prev2_wd;
1601 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1604 /* ALTER RULE <name> ON <name> */
1605 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1606 COMPLETE_WITH_CONST("RENAME TO");
1608 /* ALTER TRIGGER <name>, add ON */
1609 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1610 COMPLETE_WITH_CONST("ON");
1612 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1614 completion_info_charp = prev2_wd;
1615 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1619 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1621 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1622 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1624 /* ALTER TRIGGER <name> ON <name> */
1625 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1626 COMPLETE_WITH_CONST("RENAME TO");
1629 * If we detect ALTER TABLE <name>, suggest sub commands
1631 else if (Matches3("ALTER", "TABLE", MatchAny))
1633 static const char *const list_ALTER2[] =
1634 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1635 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1636 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", NULL};
1638 COMPLETE_WITH_LIST(list_ALTER2);
1640 /* ALTER TABLE xxx ENABLE */
1641 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1642 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1644 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1645 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1646 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1648 completion_info_charp = prev3_wd;
1649 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1651 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1653 completion_info_charp = prev4_wd;
1654 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1656 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1658 completion_info_charp = prev3_wd;
1659 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1661 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1663 completion_info_charp = prev4_wd;
1664 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1666 /* ALTER TABLE xxx INHERIT */
1667 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1668 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1669 /* ALTER TABLE xxx NO INHERIT */
1670 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1671 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1672 /* ALTER TABLE xxx DISABLE */
1673 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1674 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1675 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1677 completion_info_charp = prev3_wd;
1678 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1680 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1682 completion_info_charp = prev3_wd;
1683 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1686 /* ALTER TABLE xxx ALTER */
1687 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1688 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1690 /* ALTER TABLE xxx RENAME */
1691 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1692 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1693 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1694 COMPLETE_WITH_ATTR(prev3_wd, "");
1696 /* ALTER TABLE xxx RENAME yyy */
1697 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1698 COMPLETE_WITH_CONST("TO");
1700 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1701 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1702 COMPLETE_WITH_CONST("TO");
1704 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1705 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1706 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1707 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1708 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1709 COMPLETE_WITH_ATTR(prev3_wd, "");
1712 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1713 * provide list of constraints
1715 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1717 completion_info_charp = prev3_wd;
1718 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1720 /* ALTER TABLE ALTER [COLUMN] <foo> */
1721 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1722 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1723 COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
1724 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1725 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1726 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1727 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1728 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1729 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1730 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1731 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1732 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1733 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1734 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1735 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1736 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1737 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1738 Matches8("ALTER", "TABLE", MatchAny, "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1739 COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
1740 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1741 COMPLETE_WITH_CONST("ON");
1742 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1744 completion_info_charp = prev3_wd;
1745 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1747 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1748 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1749 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1753 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1756 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1757 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1758 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
1759 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
1760 COMPLETE_WITH_CONST("OIDS");
1761 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1762 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1763 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
1764 /* ALTER TABLE <foo> RESET */
1765 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
1766 COMPLETE_WITH_CONST("(");
1767 /* ALTER TABLE <foo> SET|RESET ( */
1768 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1770 static const char *const list_TABLEOPTIONS[] =
1772 "autovacuum_analyze_scale_factor",
1773 "autovacuum_analyze_threshold",
1774 "autovacuum_enabled",
1775 "autovacuum_freeze_max_age",
1776 "autovacuum_freeze_min_age",
1777 "autovacuum_freeze_table_age",
1778 "autovacuum_multixact_freeze_max_age",
1779 "autovacuum_multixact_freeze_min_age",
1780 "autovacuum_multixact_freeze_table_age",
1781 "autovacuum_vacuum_cost_delay",
1782 "autovacuum_vacuum_cost_limit",
1783 "autovacuum_vacuum_scale_factor",
1784 "autovacuum_vacuum_threshold",
1787 "log_autovacuum_min_duration",
1788 "toast.autovacuum_enabled",
1789 "toast.autovacuum_freeze_max_age",
1790 "toast.autovacuum_freeze_min_age",
1791 "toast.autovacuum_freeze_table_age",
1792 "toast.autovacuum_multixact_freeze_max_age",
1793 "toast.autovacuum_multixact_freeze_min_age",
1794 "toast.autovacuum_multixact_freeze_table_age",
1795 "toast.autovacuum_vacuum_cost_delay",
1796 "toast.autovacuum_vacuum_cost_limit",
1797 "toast.autovacuum_vacuum_scale_factor",
1798 "toast.autovacuum_vacuum_threshold",
1799 "toast.log_autovacuum_min_duration",
1800 "user_catalog_table",
1804 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
1806 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
1808 completion_info_charp = prev5_wd;
1809 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1811 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1812 COMPLETE_WITH_CONST("INDEX");
1813 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1814 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
1815 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
1816 COMPLETE_WITH_CONST("IDENTITY");
1818 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
1819 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
1820 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
1821 /* ALTER TABLESPACE <foo> SET|RESET */
1822 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
1823 COMPLETE_WITH_CONST("(");
1824 /* ALTER TABLESPACE <foo> SET|RESET ( */
1825 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
1826 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
1827 "effective_io_concurrency");
1829 /* ALTER TEXT SEARCH */
1830 else if (Matches3("ALTER", "TEXT", "SEARCH"))
1831 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1832 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
1833 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
1834 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
1835 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1836 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
1837 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
1839 "OWNER TO", "RENAME TO", "SET SCHEMA");
1841 /* complete ALTER TYPE <foo> with actions */
1842 else if (Matches3("ALTER", "TYPE", MatchAny))
1843 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
1845 "OWNER TO", "RENAME", "SET SCHEMA");
1846 /* complete ALTER TYPE <foo> ADD with actions */
1847 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
1848 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
1849 /* ALTER TYPE <foo> RENAME */
1850 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
1851 COMPLETE_WITH_LIST2("ATTRIBUTE", "TO");
1852 /* ALTER TYPE xxx RENAME ATTRIBUTE yyy */
1853 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny))
1854 COMPLETE_WITH_CONST("TO");
1857 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
1860 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
1861 COMPLETE_WITH_ATTR(prev3_wd, "");
1862 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
1863 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
1864 COMPLETE_WITH_CONST("TYPE");
1865 /* complete ALTER GROUP <foo> */
1866 else if (Matches3("ALTER", "GROUP", MatchAny))
1867 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
1868 /* complete ALTER GROUP <foo> ADD|DROP with USER */
1869 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
1870 COMPLETE_WITH_CONST("USER");
1871 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
1872 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
1873 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1875 /* BEGIN, END, ABORT */
1876 else if (Matches1("BEGIN|END|ABORT"))
1877 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
1879 else if (Matches1("COMMIT"))
1880 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
1881 /* RELEASE SAVEPOINT */
1882 else if (Matches1("RELEASE"))
1883 COMPLETE_WITH_CONST("SAVEPOINT");
1885 else if (Matches1("ROLLBACK"))
1886 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
1888 else if (Matches1("CLUSTER"))
1889 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
1890 else if (Matches2("CLUSTER", "VERBOSE"))
1891 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
1892 /* If we have CLUSTER <sth>, then add "USING" */
1893 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
1894 COMPLETE_WITH_CONST("USING");
1895 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
1896 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
1897 COMPLETE_WITH_CONST("USING");
1898 /* If we have CLUSTER <sth> USING, then add the index as well */
1899 else if (Matches3("CLUSTER", MatchAny, "USING") ||
1900 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
1902 completion_info_charp = prev2_wd;
1903 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1907 else if (Matches1("COMMENT"))
1908 COMPLETE_WITH_CONST("ON");
1909 else if (Matches2("COMMENT", "ON"))
1911 static const char *const list_COMMENT[] =
1912 {"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION",
1913 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
1914 "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
1915 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
1916 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
1917 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
1919 COMPLETE_WITH_LIST(list_COMMENT);
1921 else if (Matches3("COMMENT", "ON", "FOREIGN"))
1922 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1923 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
1924 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1925 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
1926 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
1927 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
1928 COMPLETE_WITH_CONST("ON");
1929 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
1931 completion_info_charp = prev2_wd;
1932 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
1934 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
1935 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
1936 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
1937 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1938 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
1939 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
1940 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
1941 COMPLETE_WITH_CONST("IS");
1946 * If we have COPY, offer list of tables or "(" (Also cover the analogous
1947 * backslash command).
1949 else if (Matches1("COPY|\\copy"))
1950 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1951 " UNION ALL SELECT '('");
1952 /* If we have COPY BINARY, complete with list of tables */
1953 else if (Matches2("COPY", "BINARY"))
1954 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1955 /* If we have COPY (, complete it with legal commands */
1956 else if (Matches2("COPY|\\copy", "("))
1957 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
1958 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
1959 else if (Matches2("COPY|\\copy", MatchAny) ||
1960 Matches3("COPY", "BINARY", MatchAny))
1961 COMPLETE_WITH_LIST2("FROM", "TO");
1962 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
1963 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
1964 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
1966 completion_charp = "";
1967 matches = completion_matches(text, complete_from_files);
1970 /* Handle COPY [BINARY] <sth> FROM|TO filename */
1971 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
1972 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
1973 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
1976 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
1977 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
1978 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
1979 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
1982 /* CREATE ACCESS METHOD */
1983 /* Complete "CREATE ACCESS METHOD <name>" */
1984 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
1985 COMPLETE_WITH_CONST("TYPE");
1986 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
1987 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
1988 COMPLETE_WITH_CONST("INDEX");
1989 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
1990 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
1991 COMPLETE_WITH_CONST("HANDLER");
1993 /* CREATE DATABASE */
1994 else if (Matches3("CREATE", "DATABASE", MatchAny))
1995 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
1997 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
1998 "LC_COLLATE", "LC_CTYPE");
2000 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2001 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2003 /* CREATE EXTENSION */
2004 /* Complete with available extensions rather than installed ones. */
2005 else if (Matches2("CREATE", "EXTENSION"))
2006 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2007 /* CREATE EXTENSION <name> */
2008 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2009 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2010 /* CREATE EXTENSION <name> VERSION */
2011 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2013 completion_info_charp = prev2_wd;
2014 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2017 /* CREATE FOREIGN */
2018 else if (Matches2("CREATE", "FOREIGN"))
2019 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2021 /* CREATE FOREIGN DATA WRAPPER */
2022 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2023 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2025 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2026 /* First off we complete CREATE UNIQUE with "INDEX" */
2027 else if (TailMatches2("CREATE", "UNIQUE"))
2028 COMPLETE_WITH_CONST("INDEX");
2029 /* If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY",
2030 and existing indexes */
2031 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2032 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2033 " UNION SELECT 'ON'"
2034 " UNION SELECT 'CONCURRENTLY'");
2035 /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
2036 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2037 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2038 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2039 /* Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing indexes */
2040 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2041 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2042 " UNION SELECT 'ON'");
2043 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2044 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2045 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2046 COMPLETE_WITH_CONST("ON");
2049 * Complete INDEX <name> ON <table> with a list of table columns (which
2050 * should really be in parens)
2052 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2053 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2054 COMPLETE_WITH_LIST2("(", "USING");
2055 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2056 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2057 COMPLETE_WITH_ATTR(prev2_wd, "");
2058 /* same if you put in USING */
2059 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2060 COMPLETE_WITH_ATTR(prev4_wd, "");
2061 /* Complete USING with an index method */
2062 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2063 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2064 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2065 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2066 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2067 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2068 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2069 COMPLETE_WITH_CONST("(");
2072 /* Complete "CREATE POLICY <name> ON" */
2073 else if (Matches3("CREATE", "POLICY", MatchAny))
2074 COMPLETE_WITH_CONST("ON");
2075 /* Complete "CREATE POLICY <name> ON <table>" */
2076 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2077 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2078 /* Complete "CREATE POLICY <name> ON <table> FOR|TO|USING|WITH CHECK" */
2079 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2080 COMPLETE_WITH_LIST4("FOR", "TO", "USING (", "WITH CHECK (");
2081 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2082 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2083 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2084 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2085 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2086 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2087 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2088 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2089 COMPLETE_WITH_LIST2("TO", "USING (");
2090 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2091 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2092 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2093 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2094 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2095 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2096 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2097 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2098 COMPLETE_WITH_CONST("(");
2101 /* Complete "CREATE RULE <sth>" with "AS ON" */
2102 else if (Matches3("CREATE", "RULE", MatchAny))
2103 COMPLETE_WITH_CONST("AS ON");
2104 /* Complete "CREATE RULE <sth> AS" with "ON" */
2105 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2106 COMPLETE_WITH_CONST("ON");
2107 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2108 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2109 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2110 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2111 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2112 COMPLETE_WITH_CONST("TO");
2113 /* Complete "AS ON <sth> TO" with a table name */
2114 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2115 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2117 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2118 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2119 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2120 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2121 "CYCLE", "OWNED BY", "START WITH");
2122 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2123 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2124 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2126 /* CREATE SERVER <name> */
2127 else if (Matches3("CREATE", "SERVER", MatchAny))
2128 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2130 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2131 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2132 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2133 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2134 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2135 else if (TailMatches2("CREATE", "UNLOGGED"))
2136 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2138 /* CREATE TABLESPACE */
2139 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2140 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2141 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2142 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2143 COMPLETE_WITH_CONST("LOCATION");
2145 /* CREATE TEXT SEARCH */
2146 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2147 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2148 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2149 COMPLETE_WITH_CONST("(");
2151 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2152 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2153 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2154 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2155 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2156 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2157 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2158 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2159 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2160 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2161 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2162 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2163 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2164 COMPLETE_WITH_LIST2("ON", "OR");
2167 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2170 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2171 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2172 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2173 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2174 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2175 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2176 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2177 COMPLETE_WITH_CONST("PROCEDURE");
2179 /* CREATE ROLE,USER,GROUP <name> */
2180 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2181 !TailMatches2("USER", "MAPPING"))
2183 static const char *const list_CREATEROLE[] =
2184 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2185 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2186 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2187 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2188 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2189 "VALID UNTIL", "WITH", NULL};
2191 COMPLETE_WITH_LIST(list_CREATEROLE);
2194 /* CREATE ROLE,USER,GROUP <name> WITH */
2195 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2197 /* Similar to the above, but don't complete "WITH" again. */
2198 static const char *const list_CREATEROLE_WITH[] =
2199 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2200 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2201 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2202 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2203 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2204 "VALID UNTIL", NULL};
2206 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2210 * complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
2213 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
2214 COMPLETE_WITH_CONST("PASSWORD");
2215 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2216 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2217 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2219 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2220 /* Complete CREATE VIEW <name> with AS */
2221 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2222 COMPLETE_WITH_CONST("AS");
2223 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2224 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2225 COMPLETE_WITH_CONST("SELECT");
2227 /* CREATE MATERIALIZED VIEW */
2228 else if (Matches2("CREATE", "MATERIALIZED"))
2229 COMPLETE_WITH_CONST("VIEW");
2230 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2231 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2232 COMPLETE_WITH_CONST("AS");
2233 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2234 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2235 COMPLETE_WITH_CONST("SELECT");
2237 /* CREATE EVENT TRIGGER */
2238 else if (Matches2("CREATE", "EVENT"))
2239 COMPLETE_WITH_CONST("TRIGGER");
2240 /* Complete CREATE EVENT TRIGGER <name> with ON */
2241 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2242 COMPLETE_WITH_CONST("ON");
2243 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2244 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2245 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2248 else if (Matches2("DECLARE", MatchAny))
2249 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2251 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2252 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2254 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2255 /* ... despite which, only complete DELETE with FROM at start of line */
2256 else if (Matches1("DELETE"))
2257 COMPLETE_WITH_CONST("FROM");
2258 /* Complete DELETE FROM with a list of tables */
2259 else if (TailMatches2("DELETE", "FROM"))
2260 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2261 /* Complete DELETE FROM <table> */
2262 else if (TailMatches3("DELETE", "FROM", MatchAny))
2263 COMPLETE_WITH_LIST2("USING", "WHERE");
2264 /* XXX: implement tab completion for DELETE ... USING */
2267 else if (Matches1("DISCARD"))
2268 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2271 else if (Matches1("DO"))
2272 COMPLETE_WITH_CONST("LANGUAGE");
2275 /* Complete DROP object with CASCADE / RESTRICT */
2276 else if (Matches3("DROP",
2277 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
2279 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2280 (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2281 ends_with(prev_wd, ')')) ||
2282 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2283 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2284 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2285 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2286 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2288 /* help completing some of the variants */
2289 else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2290 COMPLETE_WITH_CONST("(");
2291 else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2292 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2293 else if (Matches2("DROP", "FOREIGN"))
2294 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2297 else if (Matches2("DROP", "INDEX"))
2298 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2299 " UNION SELECT 'CONCURRENTLY'");
2300 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2301 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2302 else if (Matches3("DROP", "INDEX", MatchAny))
2303 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2304 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2305 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2307 /* DROP MATERIALIZED VIEW */
2308 else if (Matches2("DROP", "MATERIALIZED"))
2309 COMPLETE_WITH_CONST("VIEW");
2310 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2311 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2314 else if (Matches2("DROP", "OWNED"))
2315 COMPLETE_WITH_CONST("BY");
2316 else if (Matches3("DROP", "OWNED", "BY"))
2317 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2319 else if (Matches3("DROP", "TEXT", "SEARCH"))
2320 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2323 else if (Matches3("DROP", "TRIGGER", MatchAny))
2324 COMPLETE_WITH_CONST("ON");
2325 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2327 completion_info_charp = prev2_wd;
2328 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2330 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2331 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2333 /* DROP EVENT TRIGGER */
2334 else if (Matches2("DROP", "EVENT"))
2335 COMPLETE_WITH_CONST("TRIGGER");
2336 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2337 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2339 /* DROP POLICY <name> */
2340 else if (Matches2("DROP", "POLICY"))
2341 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2342 /* DROP POLICY <name> ON */
2343 else if (Matches3("DROP", "POLICY", MatchAny))
2344 COMPLETE_WITH_CONST("ON");
2345 /* DROP POLICY <name> ON <table> */
2346 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2348 completion_info_charp = prev2_wd;
2349 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2353 else if (Matches3("DROP", "RULE", MatchAny))
2354 COMPLETE_WITH_CONST("ON");
2355 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2357 completion_info_charp = prev2_wd;
2358 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2360 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2361 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2364 else if (Matches1("EXECUTE"))
2365 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2370 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2372 else if (Matches1("EXPLAIN"))
2373 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2374 "ANALYZE", "VERBOSE");
2375 else if (Matches2("EXPLAIN", "ANALYZE"))
2376 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2378 else if (Matches2("EXPLAIN", "VERBOSE") ||
2379 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2380 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2383 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2384 else if (Matches1("FETCH|MOVE"))
2385 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2386 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2387 else if (Matches2("FETCH|MOVE", MatchAny))
2388 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2391 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2392 * but we may as well tab-complete both: perhaps some users prefer one
2393 * variant or the other.
2395 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2396 COMPLETE_WITH_LIST2("FROM", "IN");
2398 /* FOREIGN DATA WRAPPER */
2399 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2400 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2401 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2402 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2403 /* applies in CREATE SERVER */
2404 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2405 HeadMatches2("CREATE", "SERVER"))
2406 COMPLETE_WITH_CONST("OPTIONS");
2409 else if (TailMatches2("FOREIGN", "TABLE") &&
2410 !TailMatches3("CREATE", MatchAny, MatchAny))
2411 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2413 /* FOREIGN SERVER */
2414 else if (TailMatches2("FOREIGN", "SERVER"))
2415 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2417 /* GRANT && REVOKE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2418 /* Complete GRANT/REVOKE with a list of roles and privileges */
2419 else if (TailMatches1("GRANT|REVOKE"))
2420 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2421 " UNION SELECT 'SELECT'"
2422 " UNION SELECT 'INSERT'"
2423 " UNION SELECT 'UPDATE'"
2424 " UNION SELECT 'DELETE'"
2425 " UNION SELECT 'TRUNCATE'"
2426 " UNION SELECT 'REFERENCES'"
2427 " UNION SELECT 'TRIGGER'"
2428 " UNION SELECT 'CREATE'"
2429 " UNION SELECT 'CONNECT'"
2430 " UNION SELECT 'TEMPORARY'"
2431 " UNION SELECT 'EXECUTE'"
2432 " UNION SELECT 'USAGE'"
2433 " UNION SELECT 'ALL'");
2436 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2439 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2441 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2442 COMPLETE_WITH_CONST("ON");
2443 else if (TailMatches2("GRANT", MatchAny))
2444 COMPLETE_WITH_CONST("TO");
2446 COMPLETE_WITH_CONST("FROM");
2450 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2453 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2454 * result via UNION; seems to work intuitively.
2456 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2457 * here will only work if the privilege list contains exactly one
2460 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2461 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2462 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2463 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2464 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2465 " UNION SELECT 'DATABASE'"
2466 " UNION SELECT 'DOMAIN'"
2467 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2468 " UNION SELECT 'FOREIGN SERVER'"
2469 " UNION SELECT 'FUNCTION'"
2470 " UNION SELECT 'LANGUAGE'"
2471 " UNION SELECT 'LARGE OBJECT'"
2472 " UNION SELECT 'SCHEMA'"
2473 " UNION SELECT 'SEQUENCE'"
2474 " UNION SELECT 'TABLE'"
2475 " UNION SELECT 'TABLESPACE'"
2476 " UNION SELECT 'TYPE'");
2478 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2479 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2480 "TABLES IN SCHEMA");
2482 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2483 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2486 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2487 * appropriate objects.
2489 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2491 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2493 if (TailMatches1("DATABASE"))
2494 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2495 else if (TailMatches1("DOMAIN"))
2496 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2497 else if (TailMatches1("FUNCTION"))
2498 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2499 else if (TailMatches1("LANGUAGE"))
2500 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2501 else if (TailMatches1("SCHEMA"))
2502 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2503 else if (TailMatches1("SEQUENCE"))
2504 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2505 else if (TailMatches1("TABLE"))
2506 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2507 else if (TailMatches1("TABLESPACE"))
2508 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2509 else if (TailMatches1("TYPE"))
2510 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2511 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2512 COMPLETE_WITH_CONST("TO");
2514 COMPLETE_WITH_CONST("FROM");
2518 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2519 * CURRENT_USER, or SESSION_USER.
2521 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2522 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2523 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2525 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2526 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2527 COMPLETE_WITH_CONST("TO");
2528 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2529 COMPLETE_WITH_CONST("FROM");
2531 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2532 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2534 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2535 COMPLETE_WITH_CONST("TO");
2537 COMPLETE_WITH_CONST("FROM");
2540 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2541 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2543 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2544 COMPLETE_WITH_CONST("TO");
2546 COMPLETE_WITH_CONST("FROM");
2549 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
2550 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
2552 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2553 COMPLETE_WITH_CONST("TO");
2555 COMPLETE_WITH_CONST("FROM");
2559 else if (TailMatches3("FROM", MatchAny, "GROUP"))
2560 COMPLETE_WITH_CONST("BY");
2562 /* IMPORT FOREIGN SCHEMA */
2563 else if (Matches1("IMPORT"))
2564 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
2565 else if (Matches2("IMPORT", "FOREIGN"))
2566 COMPLETE_WITH_CONST("SCHEMA");
2568 /* INSERT --- can be inside EXPLAIN, RULE, etc */
2569 /* Complete INSERT with "INTO" */
2570 else if (TailMatches1("INSERT"))
2571 COMPLETE_WITH_CONST("INTO");
2572 /* Complete INSERT INTO with table names */
2573 else if (TailMatches2("INSERT", "INTO"))
2574 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2575 /* Complete "INSERT INTO <table> (" with attribute names */
2576 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
2577 COMPLETE_WITH_ATTR(prev2_wd, "");
2580 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2581 * "TABLE" or "DEFAULT VALUES"
2583 else if (TailMatches3("INSERT", "INTO", MatchAny))
2584 COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
2587 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
2590 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
2591 ends_with(prev_wd, ')'))
2592 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
2594 /* Insert an open parenthesis after "VALUES" */
2595 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
2596 COMPLETE_WITH_CONST("(");
2599 /* Complete LOCK [TABLE] with a list of tables */
2600 else if (Matches1("LOCK"))
2601 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2602 " UNION SELECT 'TABLE'");
2603 else if (Matches2("LOCK", "TABLE"))
2604 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2606 /* For the following, handle the case of a single table only for now */
2608 /* Complete LOCK [TABLE] <table> with "IN" */
2609 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
2610 Matches3("LOCK", "TABLE", MatchAny))
2611 COMPLETE_WITH_CONST("IN");
2613 /* Complete LOCK [TABLE] <table> IN with a lock mode */
2614 else if (Matches3("LOCK", MatchAny, "IN") ||
2615 Matches4("LOCK", "TABLE", MatchAny, "IN"))
2616 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
2617 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
2618 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
2619 "SHARE ROW EXCLUSIVE MODE",
2620 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
2622 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
2623 else if (TailMatches1("NOTIFY"))
2624 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'");
2627 else if (TailMatches1("OPTIONS"))
2628 COMPLETE_WITH_CONST("(");
2630 /* OWNER TO - complete with available roles */
2631 else if (TailMatches2("OWNER", "TO"))
2632 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2635 else if (TailMatches3("FROM", MatchAny, "ORDER"))
2636 COMPLETE_WITH_CONST("BY");
2637 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
2638 COMPLETE_WITH_ATTR(prev3_wd, "");
2641 else if (Matches3("PREPARE", MatchAny, "AS"))
2642 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
2645 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
2646 * managers, not for manual use in interactive sessions.
2649 /* REASSIGN OWNED BY xxx TO yyy */
2650 else if (Matches1("REASSIGN"))
2651 COMPLETE_WITH_CONST("OWNED BY");
2652 else if (Matches2("REASSIGN", "OWNED"))
2653 COMPLETE_WITH_CONST("BY");
2654 else if (Matches3("REASSIGN", "OWNED", "BY"))
2655 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2656 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
2657 COMPLETE_WITH_CONST("TO");
2658 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
2659 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2661 /* REFRESH MATERIALIZED VIEW */
2662 else if (Matches1("REFRESH"))
2663 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
2664 else if (Matches2("REFRESH", "MATERIALIZED"))
2665 COMPLETE_WITH_CONST("VIEW");
2666 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
2667 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
2668 " UNION SELECT 'CONCURRENTLY'");
2669 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
2670 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2671 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
2672 COMPLETE_WITH_CONST("WITH");
2673 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
2674 COMPLETE_WITH_CONST("WITH");
2675 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
2676 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2677 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
2678 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2679 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
2680 COMPLETE_WITH_CONST("DATA");
2681 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
2682 COMPLETE_WITH_CONST("DATA");
2685 else if (Matches1("REINDEX"))
2686 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
2687 else if (Matches2("REINDEX", "TABLE"))
2688 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2689 else if (Matches2("REINDEX", "INDEX"))
2690 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2691 else if (Matches2("REINDEX", "SCHEMA"))
2692 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2693 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
2694 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2696 /* SECURITY LABEL */
2697 else if (Matches1("SECURITY"))
2698 COMPLETE_WITH_CONST("LABEL");
2699 else if (Matches2("SECURITY", "LABEL"))
2700 COMPLETE_WITH_LIST2("ON", "FOR");
2701 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
2702 COMPLETE_WITH_CONST("ON");
2703 else if (Matches3("SECURITY", "LABEL", "ON") ||
2704 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
2706 static const char *const list_SECURITY_LABEL[] =
2707 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
2708 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
2709 "MATERIALIZED VIEW", "LANGUAGE", "ROLE", "SCHEMA",
2710 "SEQUENCE", "TABLESPACE", "TYPE", "VIEW", NULL};
2712 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
2714 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
2715 COMPLETE_WITH_CONST("IS");
2720 /* SET, RESET, SHOW */
2721 /* Complete with a variable name */
2722 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
2723 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
2724 else if (Matches1("SHOW"))
2725 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
2726 /* Complete "SET TRANSACTION" */
2727 else if (Matches2("SET|BEGIN|START", "TRANSACTION") ||
2728 Matches2("BEGIN", "WORK") ||
2729 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
2730 COMPLETE_WITH_LIST2("ISOLATION LEVEL", "READ");
2731 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
2732 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
2733 COMPLETE_WITH_CONST("LEVEL");
2734 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL"))
2735 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
2736 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ"))
2737 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
2738 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE"))
2739 COMPLETE_WITH_CONST("READ");
2740 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ"))
2741 COMPLETE_WITH_LIST2("ONLY", "WRITE");
2742 /* SET CONSTRAINTS */
2743 else if (Matches2("SET", "CONSTRAINTS"))
2744 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
2745 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
2746 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
2747 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
2748 /* Complete SET ROLE */
2749 else if (Matches2("SET", "ROLE"))
2750 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2751 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
2752 else if (Matches2("SET", "SESSION"))
2753 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
2754 /* Complete SET SESSION AUTHORIZATION with username */
2755 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
2756 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
2757 /* Complete RESET SESSION with AUTHORIZATION */
2758 else if (Matches2("RESET", "SESSION"))
2759 COMPLETE_WITH_CONST("AUTHORIZATION");
2760 /* Complete SET <var> with "TO" */
2761 else if (Matches2("SET", MatchAny))
2762 COMPLETE_WITH_CONST("TO");
2763 /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
2764 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
2765 TailMatches2("SET", MatchAny))
2766 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
2767 /* Suggest possible variable values */
2768 else if (TailMatches3("SET", MatchAny, "TO|="))
2770 /* special cased code for individual GUCs */
2771 if (TailMatches2("DateStyle", "TO|="))
2773 static const char *const my_list[] =
2774 {"ISO", "SQL", "Postgres", "German",
2775 "YMD", "DMY", "MDY",
2776 "US", "European", "NonEuropean",
2779 COMPLETE_WITH_LIST(my_list);
2781 else if (TailMatches2("search_path", "TO|="))
2782 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
2783 " AND nspname not like 'pg\\_toast%%' "
2784 " AND nspname not like 'pg\\_temp%%' "
2785 " UNION SELECT 'DEFAULT' ");
2788 /* generic, type based, GUC support */
2789 char *guctype = get_guctype(prev2_wd);
2791 if (guctype && strcmp(guctype, "enum") == 0)
2793 char querybuf[1024];
2795 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
2796 COMPLETE_WITH_QUERY(querybuf);
2798 else if (guctype && strcmp(guctype, "bool") == 0)
2799 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
2800 "1", "0", "DEFAULT");
2802 COMPLETE_WITH_CONST("DEFAULT");
2809 /* START TRANSACTION */
2810 else if (Matches1("START"))
2811 COMPLETE_WITH_CONST("TRANSACTION");
2813 /* TABLE, but not TABLE embedded in other commands */
2814 else if (Matches1("TABLE"))
2815 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
2818 else if (TailMatches1("TABLESAMPLE"))
2819 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
2820 else if (TailMatches2("TABLESAMPLE", MatchAny))
2821 COMPLETE_WITH_CONST("(");
2824 else if (Matches1("TRUNCATE"))
2825 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2828 else if (Matches1("UNLISTEN"))
2829 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 '*'");
2831 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
2832 /* If prev. word is UPDATE suggest a list of tables */
2833 else if (TailMatches1("UPDATE"))
2834 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2835 /* Complete UPDATE <table> with "SET" */
2836 else if (TailMatches2("UPDATE", MatchAny))
2837 COMPLETE_WITH_CONST("SET");
2838 /* Complete UPDATE <table> SET with list of attributes */
2839 else if (TailMatches3("UPDATE", MatchAny, "SET"))
2840 COMPLETE_WITH_ATTR(prev2_wd, "");
2841 /* UPDATE <table> SET <attr> = */
2842 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
2843 COMPLETE_WITH_CONST("=");
2846 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
2847 COMPLETE_WITH_CONST("FOR");
2848 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
2849 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2850 " UNION SELECT 'CURRENT_USER'"
2851 " UNION SELECT 'PUBLIC'"
2852 " UNION SELECT 'USER'");
2853 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
2854 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
2855 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
2856 COMPLETE_WITH_CONST("SERVER");
2857 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
2858 COMPLETE_WITH_CONST("OPTIONS");
2861 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
2862 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
2864 else if (Matches1("VACUUM"))
2865 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2866 " UNION SELECT 'FULL'"
2867 " UNION SELECT 'FREEZE'"
2868 " UNION SELECT 'ANALYZE'"
2869 " UNION SELECT 'VERBOSE'");
2870 else if (Matches2("VACUUM", "FULL|FREEZE"))
2871 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2872 " UNION SELECT 'ANALYZE'"
2873 " UNION SELECT 'VERBOSE'");
2874 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
2875 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2876 " UNION SELECT 'VERBOSE'");
2877 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
2878 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2879 " UNION SELECT 'ANALYZE'");
2880 else if (Matches2("VACUUM", "VERBOSE"))
2881 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2882 " UNION SELECT 'ANALYZE'");
2883 else if (Matches2("VACUUM", "ANALYZE"))
2884 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2885 " UNION SELECT 'VERBOSE'");
2886 else if (HeadMatches1("VACUUM"))
2887 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2889 /* WITH [RECURSIVE] */
2892 * Only match when WITH is the first word, as WITH may appear in many
2895 else if (Matches1("WITH"))
2896 COMPLETE_WITH_CONST("RECURSIVE");
2899 /* Complete with list of tables */
2900 else if (Matches1("ANALYZE"))
2901 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
2904 /* Simple case of the word before the where being the table name */
2905 else if (TailMatches2(MatchAny, "WHERE"))
2906 COMPLETE_WITH_ATTR(prev2_wd, "");
2909 /* TODO: also include SRF ? */
2910 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
2911 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2914 else if (TailMatches1("JOIN"))
2915 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2917 /* Backslash commands */
2918 /* TODO: \dc \dd \dl */
2919 else if (TailMatchesCS1("\\?"))
2920 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
2921 else if (TailMatchesCS1("\\connect|\\c"))
2923 if (!recognized_connection_string(text))
2924 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2926 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
2928 if (!recognized_connection_string(prev_wd))
2929 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2931 else if (TailMatchesCS1("\\da*"))
2932 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
2933 else if (TailMatchesCS1("\\db*"))
2934 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2935 else if (TailMatchesCS1("\\dD*"))
2936 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2937 else if (TailMatchesCS1("\\des*"))
2938 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2939 else if (TailMatchesCS1("\\deu*"))
2940 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
2941 else if (TailMatchesCS1("\\dew*"))
2942 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2943 else if (TailMatchesCS1("\\df*"))
2944 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2946 else if (TailMatchesCS1("\\dFd*"))
2947 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
2948 else if (TailMatchesCS1("\\dFp*"))
2949 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
2950 else if (TailMatchesCS1("\\dFt*"))
2951 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
2952 /* must be at end of \dF alternatives: */
2953 else if (TailMatchesCS1("\\dF*"))
2954 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
2956 else if (TailMatchesCS1("\\di*"))
2957 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2958 else if (TailMatchesCS1("\\dL*"))
2959 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2960 else if (TailMatchesCS1("\\dn*"))
2961 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2962 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
2963 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2964 else if (TailMatchesCS1("\\ds*"))
2965 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2966 else if (TailMatchesCS1("\\dt*"))
2967 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2968 else if (TailMatchesCS1("\\dT*"))
2969 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2970 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
2971 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2972 else if (TailMatchesCS1("\\dv*"))
2973 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2974 else if (TailMatchesCS1("\\dx*"))
2975 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
2976 else if (TailMatchesCS1("\\dm*"))
2977 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2978 else if (TailMatchesCS1("\\dE*"))
2979 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2980 else if (TailMatchesCS1("\\dy*"))
2981 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2983 /* must be at end of \d alternatives: */
2984 else if (TailMatchesCS1("\\d*"))
2985 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
2987 else if (TailMatchesCS1("\\ef"))
2988 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2989 else if (TailMatchesCS1("\\ev"))
2990 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2992 else if (TailMatchesCS1("\\encoding"))
2993 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
2994 else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
2995 COMPLETE_WITH_LIST(sql_commands);
2996 else if (TailMatchesCS1("\\password"))
2997 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2998 else if (TailMatchesCS1("\\pset"))
3000 static const char *const my_list[] =
3001 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3002 "footer", "format", "linestyle", "null", "numericlocale",
3003 "pager", "recordsep", "recordsep_zero", "tableattr", "title",
3004 "tuples_only", "unicode_border_linestyle",
3005 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3007 COMPLETE_WITH_LIST_CS(my_list);
3009 else if (TailMatchesCS2("\\pset", MatchAny))
3011 if (TailMatchesCS1("format"))
3013 static const char *const my_list[] =
3014 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3015 "latex", "latex-longtable", "troff-ms", NULL};
3017 COMPLETE_WITH_LIST_CS(my_list);
3019 else if (TailMatchesCS1("linestyle"))
3020 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3021 else if (TailMatchesCS1("unicode_border_linestyle|"
3022 "unicode_column_linestyle|"
3023 "unicode_header_linestyle"))
3024 COMPLETE_WITH_LIST_CS2("single", "double");
3026 else if (TailMatchesCS1("\\unset"))
3028 matches = complete_from_variables(text, "", "", true);
3030 else if (TailMatchesCS1("\\set"))
3032 matches = complete_from_variables(text, "", "", false);
3034 else if (TailMatchesCS2("\\set", MatchAny))
3036 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3037 "SINGLELINE|SINGLESTEP"))
3038 COMPLETE_WITH_LIST_CS2("on", "off");
3039 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3040 COMPLETE_WITH_LIST_CS4("lower", "upper",
3041 "preserve-lower", "preserve-upper");
3042 else if (TailMatchesCS1("ECHO"))
3043 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3044 else if (TailMatchesCS1("ECHO_HIDDEN"))
3045 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3046 else if (TailMatchesCS1("HISTCONTROL"))
3047 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3048 "ignoreboth", "none");
3049 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3050 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3051 else if (TailMatchesCS1("SHOW_CONTEXT"))
3052 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3053 else if (TailMatchesCS1("VERBOSITY"))
3054 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3056 else if (TailMatchesCS1("\\sf*"))
3057 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3058 else if (TailMatchesCS1("\\sv*"))
3059 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3060 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3061 "\\ir|\\include_relative|\\o|\\out|"
3062 "\\s|\\w|\\write|\\lo_import"))
3064 completion_charp = "\\";
3065 matches = completion_matches(text, complete_from_files);
3069 * Finally, we look through the list of "things", such as TABLE, INDEX and
3070 * check if that was the previous word. If so, execute the query to get a
3077 for (i = 0; words_after_create[i].name; i++)
3079 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3081 if (words_after_create[i].query)
3082 COMPLETE_WITH_QUERY(words_after_create[i].query);
3083 else if (words_after_create[i].squery)
3084 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3092 * If we still don't have anything to match we have to fabricate some sort
3093 * of default list. If we were to just return NULL, readline automatically
3094 * attempts filename completion, and that's usually no good.
3096 if (matches == NULL)
3098 COMPLETE_WITH_CONST("");
3099 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3100 rl_completion_append_character = '\0';
3105 free(previous_words);
3108 /* Return our Grand List O' Matches */
3114 * GENERATOR FUNCTIONS
3116 * These functions do all the actual work of completing the input. They get
3117 * passed the text so far and the count how many times they have been called
3118 * so far with the same text.
3119 * If you read the above carefully, you'll see that these don't get called
3120 * directly but through the readline interface.
3121 * The return value is expected to be the full completion of the text, going
3122 * through a list each time, or NULL if there are no more matches. The string
3123 * will be free()'d by readline, so you must run it through strdup() or
3124 * something of that sort.
3128 * Common routine for create_command_generator and drop_command_generator.
3129 * Entries that have 'excluded' flags are not returned.
3132 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3134 static int list_index,
3138 /* If this is the first time for this completion, init some values */
3142 string_length = strlen(text);
3145 /* find something that matches */
3146 while ((name = words_after_create[list_index++].name))
3148 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3149 !(words_after_create[list_index - 1].flags & excluded))
3150 return pg_strdup_keyword_case(name, text);
3152 /* if nothing matches, return NULL */
3157 * This one gives you one from a list of things you can put after CREATE
3161 create_command_generator(const char *text, int state)
3163 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3167 * This function gives you a list of things you can put after a DROP command.
3170 drop_command_generator(const char *text, int state)
3172 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3175 /* The following two functions are wrappers for _complete_from_query */
3178 complete_from_query(const char *text, int state)
3180 return _complete_from_query(0, text, state);
3184 complete_from_schema_query(const char *text, int state)
3186 return _complete_from_query(1, text, state);
3191 * This creates a list of matching things, according to a query pointed to
3192 * by completion_charp.
3193 * The query can be one of two kinds:
3195 * 1. A simple query which must contain a %d and a %s, which will be replaced
3196 * by the string length of the text and the text itself. The query may also
3197 * have up to four more %s in it; the first two such will be replaced by the
3198 * value of completion_info_charp, the next two by the value of
3199 * completion_info_charp2.
3201 * 2. A schema query used for completion of both schema and relation names.
3202 * These are more complex and must contain in the following order:
3203 * %d %s %d %s %d %s %s %d %s
3204 * where %d is the string length of the text and %s the text itself.
3206 * It is assumed that strings should be escaped to become SQL literals
3207 * (that is, what is in the query is actually ... '%s' ...)
3209 * See top of file for examples of both kinds of query.
3212 _complete_from_query(int is_schema_query, const char *text, int state)
3214 static int list_index,
3216 static PGresult *result = NULL;
3218 * If this is the first time for this completion, we fetch a list of our
3219 * "things" from the backend.
3223 PQExpBufferData query_buffer;
3226 char *e_info_charp2;
3227 const char *pstr = text;
3228 int char_length = 0;
3231 byte_length = strlen(text);
3233 /* Count length as number of characters (not bytes), for passing to substring */
3237 pstr += PQmblen(pstr, pset.encoding);
3240 /* Free any prior result */
3244 /* Set up suitably-escaped copies of textual inputs */
3245 e_text = escape_string(text);
3247 if (completion_info_charp)
3248 e_info_charp = escape_string(completion_info_charp);
3250 e_info_charp = NULL;
3252 if (completion_info_charp2)
3253 e_info_charp2 = escape_string(completion_info_charp2);
3255 e_info_charp2 = NULL;
3257 initPQExpBuffer(&query_buffer);
3259 if (is_schema_query)
3261 /* completion_squery gives us the pieces to assemble */
3262 const char *qualresult = completion_squery->qualresult;
3264 if (qualresult == NULL)
3265 qualresult = completion_squery->result;
3267 /* Get unqualified names matching the input-so-far */
3268 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3269 completion_squery->result,
3270 completion_squery->catname);
3271 if (completion_squery->selcondition)
3272 appendPQExpBuffer(&query_buffer, "%s AND ",
3273 completion_squery->selcondition);
3274 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3275 completion_squery->result,
3276 char_length, e_text);
3277 appendPQExpBuffer(&query_buffer, " AND %s",
3278 completion_squery->viscondition);
3281 * When fetching relation names, suppress system catalogs unless
3282 * the input-so-far begins with "pg_". This is a compromise
3283 * between not offering system catalogs for completion at all, and
3284 * having them swamp the result when the input is just "p".
3286 if (strcmp(completion_squery->catname,
3287 "pg_catalog.pg_class c") == 0 &&
3288 strncmp(text, "pg_", 3) !=0)
3290 appendPQExpBufferStr(&query_buffer,
3291 " AND c.relnamespace <> (SELECT oid FROM"
3292 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3296 * Add in matching schema names, but only if there is more than
3297 * one potential match among schema names.
3299 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3300 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3301 "FROM pg_catalog.pg_namespace n "
3302 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3303 char_length, e_text);
3304 appendPQExpBuffer(&query_buffer,
3305 " AND (SELECT pg_catalog.count(*)"
3306 " FROM pg_catalog.pg_namespace"
3307 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3308 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3309 char_length, e_text);
3312 * Add in matching qualified names, but only if there is exactly
3313 * one schema matching the input-so-far.
3315 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3316 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3317 "FROM %s, pg_catalog.pg_namespace n "
3318 "WHERE %s = n.oid AND ",
3320 completion_squery->catname,
3321 completion_squery->namespace);
3322 if (completion_squery->selcondition)
3323 appendPQExpBuffer(&query_buffer, "%s AND ",
3324 completion_squery->selcondition);
3325 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3327 char_length, e_text);
3330 * This condition exploits the single-matching-schema rule to
3331 * speed up the query
3333 appendPQExpBuffer(&query_buffer,
3334 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3335 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3336 char_length, e_text);
3337 appendPQExpBuffer(&query_buffer,
3338 " AND (SELECT pg_catalog.count(*)"
3339 " FROM pg_catalog.pg_namespace"
3340 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3341 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3342 char_length, e_text);
3344 /* If an addon query was provided, use it */
3345 if (completion_charp)
3346 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3350 /* completion_charp is an sprintf-style format string */
3351 appendPQExpBuffer(&query_buffer, completion_charp,
3352 char_length, e_text,
3353 e_info_charp, e_info_charp,
3354 e_info_charp2, e_info_charp2);
3357 /* Limit the number of records in the result */
3358 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3359 completion_max_records);
3361 result = exec_query(query_buffer.data);
3363 termPQExpBuffer(&query_buffer);
3368 free(e_info_charp2);
3371 /* Find something that matches */
3372 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3376 while (list_index < PQntuples(result) &&
3377 (item = PQgetvalue(result, list_index++, 0)))
3378 if (pg_strncasecmp(text, item, byte_length) == 0)
3379 return pg_strdup(item);
3382 /* If nothing matches, free the db structure and return null */
3390 * This function returns in order one of a fixed, NULL pointer terminated list
3391 * of strings (if matching). This can be used if there are only a fixed number
3392 * SQL words that can appear at certain spot.
3395 complete_from_list(const char *text, int state)
3397 static int string_length,
3400 static bool casesensitive;
3403 /* need to have a list */
3404 Assert(completion_charpp != NULL);
3406 /* Initialization */
3410 string_length = strlen(text);
3411 casesensitive = completion_case_sensitive;
3415 while ((item = completion_charpp[list_index++]))
3417 /* First pass is case sensitive */
3418 if (casesensitive && strncmp(text, item, string_length) == 0)
3421 return pg_strdup(item);
3424 /* Second pass is case insensitive, don't bother counting matches */
3425 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3427 if (completion_case_sensitive)
3428 return pg_strdup(item);
3432 * If case insensitive matching was requested initially,
3433 * adjust the case according to setting.
3435 return pg_strdup_keyword_case(item, text);
3440 * No matches found. If we're not case insensitive already, lets switch to
3441 * being case insensitive and try again
3443 if (casesensitive && matches == 0)
3445 casesensitive = false;
3448 return complete_from_list(text, state);
3451 /* If no more matches, return null. */
3457 * This function returns one fixed string the first time even if it doesn't
3458 * match what's there, and nothing the second time. This should be used if
3459 * there is only one possibility that can appear at a certain spot, so
3460 * misspellings will be overwritten. The string to be passed must be in
3464 complete_from_const(const char *text, int state)
3466 Assert(completion_charp != NULL);
3469 if (completion_case_sensitive)
3470 return pg_strdup(completion_charp);
3474 * If case insensitive matching was requested initially, adjust
3475 * the case according to setting.
3477 return pg_strdup_keyword_case(completion_charp, text);
3485 * This function appends the variable name with prefix and suffix to
3486 * the variable names array.
3489 append_variable_names(char ***varnames, int *nvars,
3490 int *maxvars, const char *varname,
3491 const char *prefix, const char *suffix)
3493 if (*nvars >= *maxvars)
3496 *varnames = (char **) pg_realloc(*varnames,
3497 ((*maxvars) + 1) * sizeof(char *));
3500 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3505 * This function supports completion with the name of a psql variable.
3506 * The variable names can be prefixed and suffixed with additional text
3507 * to support quoting usages. If need_value is true, only the variables
3508 * that have the set values are picked up.
3511 complete_from_variables(const char *text, const char *prefix, const char *suffix,
3519 struct _variable *ptr;
3521 static const char *const known_varnames[] = {
3522 "AUTOCOMMIT", "COMP_KEYWORD_CASE", "DBNAME", "ECHO", "ECHO_HIDDEN",
3523 "ENCODING", "FETCH_COUNT", "HISTCONTROL", "HISTFILE", "HISTSIZE",
3524 "HOST", "IGNOREEOF", "LASTOID", "ON_ERROR_ROLLBACK", "ON_ERROR_STOP",
3525 "PORT", "PROMPT1", "PROMPT2", "PROMPT3", "QUIET",
3526 "SHOW_CONTEXT", "SINGLELINE", "SINGLESTEP",
3527 "USER", "VERBOSITY", NULL
3530 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
3534 for (i = 0; known_varnames[i] && nvars < maxvars; i++)
3535 append_variable_names(&varnames, &nvars, &maxvars,
3536 known_varnames[i], prefix, suffix);
3539 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3541 if (need_value && !(ptr->value))
3543 for (i = 0; known_varnames[i]; i++) /* remove duplicate entry */
3545 if (strcmp(ptr->name, known_varnames[i]) == 0)
3548 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3552 varnames[nvars] = NULL;
3553 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
3555 for (i = 0; i < nvars; i++)
3564 * This function wraps rl_filename_completion_function() to strip quotes from
3565 * the input before searching for matches and to quote any matches for which
3566 * the consuming command will require it.
3569 complete_from_files(const char *text, int state)
3571 static const char *unquoted_text;
3572 char *unquoted_match;
3577 /* Initialization: stash the unquoted input. */
3578 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
3579 false, true, pset.encoding);
3580 /* expect a NULL return for the empty string only */
3583 Assert(*text == '\0');
3584 unquoted_text = text;
3588 unquoted_match = filename_completion_function(unquoted_text, state);
3592 * Caller sets completion_charp to a zero- or one-character string
3593 * containing the escape character. This is necessary since \copy has
3594 * no escape character, but every other backslash command recognizes
3595 * "\" as an escape character. Since we have only two callers, don't
3596 * bother providing a macro to simplify this.
3598 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
3599 '\'', *completion_charp, pset.encoding);
3601 free(unquoted_match);
3603 ret = unquoted_match;
3610 /* HELPER FUNCTIONS */
3614 * Make a pg_strdup copy of s and convert the case according to
3615 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
3618 pg_strdup_keyword_case(const char *s, const char *ref)
3622 unsigned char first = ref[0];
3626 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
3627 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
3628 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
3629 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
3631 for (p = ret; *p; p++)
3632 *p = pg_tolower((unsigned char) *p);
3636 for (p = ret; *p; p++)
3637 *p = pg_toupper((unsigned char) *p);
3645 * escape_string - Escape argument for use as string literal.
3647 * The returned value has to be freed.
3650 escape_string(const char *text)
3655 text_length = strlen(text);
3657 result = pg_malloc(text_length * 2 + 1);
3658 PQescapeStringConn(pset.db, result, text, text_length, NULL);
3665 * Execute a query and report any errors. This should be the preferred way of
3666 * talking to the database in this file.
3669 exec_query(const char *query)
3673 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
3676 result = PQexec(pset.db, query);
3678 if (PQresultStatus(result) != PGRES_TUPLES_OK)
3681 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
3682 PQerrorMessage(pset.db), query);
3693 * Parse all the word(s) before point.
3695 * Returns a malloc'd array of character pointers that point into the malloc'd
3696 * data array returned to *buffer; caller must free() both of these when done.
3697 * *nwords receives the number of words found, ie, the valid length of the
3700 * Words are returned right to left, that is, previous_words[0] gets the last
3701 * word before point, previous_words[1] the next-to-last, etc.
3704 get_previous_words(int point, char **buffer, int *nwords)
3706 char **previous_words;
3709 int words_found = 0;
3713 * If we have anything in tab_completion_query_buf, paste it together with
3714 * rl_line_buffer to construct the full query. Otherwise we can just use
3715 * rl_line_buffer as the input string.
3717 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
3719 i = tab_completion_query_buf->len;
3720 buf = pg_malloc(point + i + 2);
3721 memcpy(buf, tab_completion_query_buf->data, i);
3723 memcpy(buf + i, rl_line_buffer, point);
3726 /* Readjust point to reference appropriate offset in buf */
3730 buf = rl_line_buffer;
3733 * Allocate an array of string pointers and a buffer to hold the strings
3734 * themselves. The worst case is that the line contains only
3735 * non-whitespace WORD_BREAKS characters, making each one a separate word.
3736 * This is usually much more space than we need, but it's cheaper than
3737 * doing a separate malloc() for each word.
3739 previous_words = (char **) pg_malloc(point * sizeof(char *));
3740 *buffer = outptr = (char *) pg_malloc(point * 2);
3743 * First we look for a non-word char before the current point. (This is
3744 * probably useless, if readline is on the same page as we are about what
3745 * is a word, but if so it's cheap.)
3747 for (i = point - 1; i >= 0; i--)
3749 if (strchr(WORD_BREAKS, buf[i]))
3755 * Now parse words, working backwards, until we hit start of line. The
3756 * backwards scan has some interesting but intentional properties
3757 * concerning parenthesis handling.
3763 bool inquotes = false;
3764 int parentheses = 0;
3766 /* now find the first non-space which then constitutes the end */
3768 for (i = point; i >= 0; i--)
3770 if (!isspace((unsigned char) buf[i]))
3776 /* if no end found, we're done */
3781 * Otherwise we now look for the start. The start is either the last
3782 * character before any word-break character going backwards from the
3783 * end, or it's simply character 0. We also handle open quotes and
3786 for (start = end; start > 0; start--)
3788 if (buf[start] == '"')
3789 inquotes = !inquotes;
3792 if (buf[start] == ')')
3794 else if (buf[start] == '(')
3796 if (--parentheses <= 0)
3799 else if (parentheses == 0 &&
3800 strchr(WORD_BREAKS, buf[start - 1]))
3805 /* Return the word located at start to end inclusive */
3806 previous_words[words_found++] = outptr;
3807 i = end - start + 1;
3808 memcpy(outptr, &buf[start], i);
3812 /* Continue searching */
3816 /* Release parsing input workspace, if we made one above */
3817 if (buf != rl_line_buffer)
3820 *nwords = words_found;
3821 return previous_words;
3825 * Look up the type for the GUC variable with the passed name.
3827 * Returns NULL if the variable is unknown. Otherwise the returned string,
3828 * containing the type, has to be freed.
3831 get_guctype(const char *varname)
3833 PQExpBufferData query_buffer;
3836 char *guctype = NULL;
3838 e_varname = escape_string(varname);
3840 initPQExpBuffer(&query_buffer);
3841 appendPQExpBuffer(&query_buffer,
3842 "SELECT vartype FROM pg_catalog.pg_settings "
3843 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
3846 result = exec_query(query_buffer.data);
3847 termPQExpBuffer(&query_buffer);
3850 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
3851 guctype = pg_strdup(PQgetvalue(result, 0, 0));
3861 * Surround a string with single quotes. This works for both SQL and
3862 * psql internal. Currently disabled because it is reported not to
3863 * cooperate with certain versions of readline.
3866 quote_file_name(char *text, int match_type, char *quote_pointer)
3871 (void) quote_pointer; /* not used */
3873 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
3874 s = pg_malloc(length);
3876 strcpy(s + 1, text);
3877 if (match_type == SINGLE_MATCH)
3878 s[length - 2] = '\'';
3879 s[length - 1] = '\0';
3884 dequote_file_name(char *text, char quote_char)
3890 return pg_strdup(text);
3892 length = strlen(text);
3893 s = pg_malloc(length - 2 + 1);
3894 strlcpy(s, text +1, length - 2 + 1);
3898 #endif /* NOT_USED */
3900 #endif /* USE_READLINE */