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",
1278 "\\copyright", "\\crosstabview",
1279 "\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD",
1280 "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df",
1281 "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
1282 "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS",
1283 "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy",
1284 "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev",
1285 "\\f", "\\g", "\\gexec", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
1286 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
1287 "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
1288 "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t", "\\T",
1289 "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL
1292 (void) end; /* "end" is not used */
1294 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1295 rl_completion_append_character = ' ';
1298 /* Clear a few things. */
1299 completion_charp = NULL;
1300 completion_charpp = NULL;
1301 completion_info_charp = NULL;
1302 completion_info_charp2 = NULL;
1305 * Scan the input line to extract the words before our current position.
1306 * According to those we'll make some smart decisions on what the user is
1307 * probably intending to type.
1309 previous_words = get_previous_words(start,
1311 &previous_words_count);
1313 /* If current word is a backslash command, offer completions for that */
1314 if (text[0] == '\\')
1315 COMPLETE_WITH_LIST_CS(backslash_commands);
1317 /* If current word is a variable interpolation, handle that case */
1318 else if (text[0] == ':' && text[1] != ':')
1320 if (text[1] == '\'')
1321 matches = complete_from_variables(text, ":'", "'", true);
1322 else if (text[1] == '"')
1323 matches = complete_from_variables(text, ":\"", "\"", true);
1325 matches = complete_from_variables(text, ":", "", true);
1328 /* If no previous word, suggest one of the basic sql commands */
1329 else if (previous_words_count == 0)
1330 COMPLETE_WITH_LIST(sql_commands);
1333 /* complete with something you can create */
1334 else if (TailMatches1("CREATE"))
1335 matches = completion_matches(text, create_command_generator);
1337 /* DROP, but not DROP embedded in other commands */
1338 /* complete with something you can drop */
1339 else if (Matches1("DROP"))
1340 matches = completion_matches(text, drop_command_generator);
1345 else if (Matches2("ALTER", "TABLE"))
1346 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1347 "UNION SELECT 'ALL IN TABLESPACE'");
1349 /* ALTER something */
1350 else if (Matches1("ALTER"))
1352 static const char *const list_ALTER[] =
1353 {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
1354 "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
1355 "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR",
1356 "POLICY", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM", "TABLE",
1357 "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
1358 "USER", "USER MAPPING FOR", "VIEW", NULL};
1360 COMPLETE_WITH_LIST(list_ALTER);
1362 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
1363 else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
1364 COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
1365 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
1366 else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
1367 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1368 /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
1369 else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
1370 COMPLETE_WITH_CONST("SET TABLESPACE");
1371 /* ALTER AGGREGATE,FUNCTION <name> */
1372 else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
1373 COMPLETE_WITH_CONST("(");
1374 /* ALTER AGGREGATE,FUNCTION <name> (...) */
1375 else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
1377 if (ends_with(prev_wd, ')'))
1378 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1380 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
1383 /* ALTER SCHEMA <name> */
1384 else if (Matches3("ALTER", "SCHEMA", MatchAny))
1385 COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
1387 /* ALTER COLLATION <name> */
1388 else if (Matches3("ALTER", "COLLATION", MatchAny))
1389 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1391 /* ALTER CONVERSION <name> */
1392 else if (Matches3("ALTER", "CONVERSION", MatchAny))
1393 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1395 /* ALTER DATABASE <name> */
1396 else if (Matches3("ALTER", "DATABASE", MatchAny))
1397 COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
1398 "IS_TEMPLATE", "ALLOW_CONNECTIONS",
1399 "CONNECTION LIMIT");
1401 /* ALTER EVENT TRIGGER */
1402 else if (Matches3("ALTER", "EVENT", "TRIGGER"))
1403 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1405 /* ALTER EVENT TRIGGER <name> */
1406 else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
1407 COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
1409 /* ALTER EVENT TRIGGER <name> ENABLE */
1410 else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
1411 COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
1413 /* ALTER EXTENSION <name> */
1414 else if (Matches3("ALTER", "EXTENSION", MatchAny))
1415 COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
1418 else if (Matches2("ALTER", "FOREIGN"))
1419 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1421 /* ALTER FOREIGN DATA WRAPPER <name> */
1422 else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
1423 COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
1425 /* ALTER FOREIGN TABLE <name> */
1426 else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
1428 static const char *const list_ALTER_FOREIGN_TABLE[] =
1429 {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
1430 "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET",
1431 "VALIDATE CONSTRAINT", NULL};
1433 COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE);
1437 else if (Matches2("ALTER", "INDEX"))
1438 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
1439 "UNION SELECT 'ALL IN TABLESPACE'");
1440 /* ALTER INDEX <name> */
1441 else if (Matches3("ALTER", "INDEX", MatchAny))
1442 COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
1443 /* ALTER INDEX <name> SET */
1444 else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
1445 COMPLETE_WITH_LIST2("(", "TABLESPACE");
1446 /* ALTER INDEX <name> RESET */
1447 else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
1448 COMPLETE_WITH_CONST("(");
1449 /* ALTER INDEX <foo> SET|RESET ( */
1450 else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
1451 COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
1452 "gin_pending_list_limit");
1453 else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
1454 COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
1455 "gin_pending_list_limit =");
1457 /* ALTER LANGUAGE <name> */
1458 else if (Matches3("ALTER", "LANGUAGE", MatchAny))
1459 COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
1461 /* ALTER LARGE OBJECT <oid> */
1462 else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
1463 COMPLETE_WITH_CONST("OWNER TO");
1465 /* ALTER MATERIALIZED VIEW */
1466 else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
1467 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
1468 "UNION SELECT 'ALL IN TABLESPACE'");
1470 /* ALTER USER,ROLE <name> */
1471 else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
1472 !TailMatches2("USER", "MAPPING"))
1474 static const char *const list_ALTERUSER[] =
1475 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1476 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1477 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1478 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1479 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1480 "VALID UNTIL", "WITH", NULL};
1482 COMPLETE_WITH_LIST(list_ALTERUSER);
1485 /* ALTER USER,ROLE <name> WITH */
1486 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
1488 /* Similar to the above, but don't complete "WITH" again. */
1489 static const char *const list_ALTERUSER_WITH[] =
1490 {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
1491 "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
1492 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
1493 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
1494 "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
1495 "VALID UNTIL", NULL};
1497 COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
1500 /* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
1501 else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
1502 COMPLETE_WITH_CONST("PASSWORD");
1503 /* ALTER DEFAULT PRIVILEGES */
1504 else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
1505 COMPLETE_WITH_LIST3("FOR ROLE", "FOR USER", "IN SCHEMA");
1506 /* ALTER DEFAULT PRIVILEGES FOR */
1507 else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
1508 COMPLETE_WITH_LIST2("ROLE", "USER");
1509 /* ALTER DEFAULT PRIVILEGES { FOR ROLE ... | IN SCHEMA ... } */
1510 else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER", MatchAny) ||
1511 Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA", MatchAny))
1512 COMPLETE_WITH_LIST2("GRANT", "REVOKE");
1513 /* ALTER DOMAIN <name> */
1514 else if (Matches3("ALTER", "DOMAIN", MatchAny))
1515 COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
1516 "VALIDATE CONSTRAINT");
1517 /* ALTER DOMAIN <sth> DROP */
1518 else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
1519 COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
1520 /* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
1521 else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
1523 completion_info_charp = prev3_wd;
1524 COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
1526 /* ALTER DOMAIN <sth> RENAME */
1527 else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
1528 COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
1529 /* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
1530 else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
1531 COMPLETE_WITH_CONST("TO");
1533 /* ALTER DOMAIN <sth> SET */
1534 else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
1535 COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
1536 /* ALTER SEQUENCE <name> */
1537 else if (Matches3("ALTER", "SEQUENCE", MatchAny))
1539 static const char *const list_ALTERSEQUENCE[] =
1540 {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
1541 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
1543 COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
1545 /* ALTER SEQUENCE <name> NO */
1546 else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
1547 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
1548 /* ALTER SERVER <name> */
1549 else if (Matches3("ALTER", "SERVER", MatchAny))
1550 COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
1551 /* ALTER SERVER <name> VERSION <version>*/
1552 else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
1553 COMPLETE_WITH_CONST("OPTIONS");
1554 /* ALTER SYSTEM SET, RESET, RESET ALL */
1555 else if (Matches2("ALTER", "SYSTEM"))
1556 COMPLETE_WITH_LIST2("SET", "RESET");
1557 /* ALTER SYSTEM SET|RESET <name> */
1558 else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
1559 COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
1560 /* ALTER VIEW <name> */
1561 else if (Matches3("ALTER", "VIEW", MatchAny))
1562 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1564 /* ALTER MATERIALIZED VIEW <name> */
1565 else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
1566 COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
1569 /* ALTER POLICY <name> */
1570 else if (Matches2("ALTER", "POLICY"))
1571 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
1572 /* ALTER POLICY <name> ON */
1573 else if (Matches3("ALTER", "POLICY", MatchAny))
1574 COMPLETE_WITH_CONST("ON");
1575 /* ALTER POLICY <name> ON <table> */
1576 else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
1578 completion_info_charp = prev2_wd;
1579 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
1581 /* ALTER POLICY <name> ON <table> - show options */
1582 else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
1583 COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
1584 /* ALTER POLICY <name> ON <table> TO <role> */
1585 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
1586 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
1587 /* ALTER POLICY <name> ON <table> USING ( */
1588 else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
1589 COMPLETE_WITH_CONST("(");
1590 /* ALTER POLICY <name> ON <table> WITH CHECK ( */
1591 else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
1592 COMPLETE_WITH_CONST("(");
1594 /* ALTER RULE <name>, add ON */
1595 else if (Matches3("ALTER", "RULE", MatchAny))
1596 COMPLETE_WITH_CONST("ON");
1598 /* If we have ALTER RULE <name> ON, then add the correct tablename */
1599 else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
1601 completion_info_charp = prev2_wd;
1602 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
1605 /* ALTER RULE <name> ON <name> */
1606 else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
1607 COMPLETE_WITH_CONST("RENAME TO");
1609 /* ALTER TRIGGER <name>, add ON */
1610 else if (Matches3("ALTER", "TRIGGER", MatchAny))
1611 COMPLETE_WITH_CONST("ON");
1613 else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
1615 completion_info_charp = prev2_wd;
1616 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
1620 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
1622 else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
1623 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1625 /* ALTER TRIGGER <name> ON <name> */
1626 else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
1627 COMPLETE_WITH_CONST("RENAME TO");
1630 * If we detect ALTER TABLE <name>, suggest sub commands
1632 else if (Matches3("ALTER", "TABLE", MatchAny))
1634 static const char *const list_ALTER2[] =
1635 {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
1636 "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET",
1637 "VALIDATE CONSTRAINT", "REPLICA IDENTITY", NULL};
1639 COMPLETE_WITH_LIST(list_ALTER2);
1641 /* ALTER TABLE xxx ENABLE */
1642 else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
1643 COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
1645 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
1646 COMPLETE_WITH_LIST2("RULE", "TRIGGER");
1647 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
1649 completion_info_charp = prev3_wd;
1650 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1652 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
1654 completion_info_charp = prev4_wd;
1655 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1657 else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
1659 completion_info_charp = prev3_wd;
1660 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1662 else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
1664 completion_info_charp = prev4_wd;
1665 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1667 /* ALTER TABLE xxx INHERIT */
1668 else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
1669 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1670 /* ALTER TABLE xxx NO INHERIT */
1671 else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
1672 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
1673 /* ALTER TABLE xxx DISABLE */
1674 else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
1675 COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
1676 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
1678 completion_info_charp = prev3_wd;
1679 COMPLETE_WITH_QUERY(Query_for_rule_of_table);
1681 else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
1683 completion_info_charp = prev3_wd;
1684 COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
1687 /* ALTER TABLE xxx ALTER */
1688 else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
1689 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
1691 /* ALTER TABLE xxx RENAME */
1692 else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
1693 COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
1694 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
1695 COMPLETE_WITH_ATTR(prev3_wd, "");
1697 /* ALTER TABLE xxx RENAME yyy */
1698 else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
1699 COMPLETE_WITH_CONST("TO");
1701 /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
1702 else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
1703 COMPLETE_WITH_CONST("TO");
1705 /* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
1706 else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
1707 COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
1708 /* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
1709 else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
1710 COMPLETE_WITH_ATTR(prev3_wd, "");
1713 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
1714 * provide list of constraints
1716 else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
1718 completion_info_charp = prev3_wd;
1719 COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
1721 /* ALTER TABLE ALTER [COLUMN] <foo> */
1722 else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
1723 Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
1724 COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
1725 /* ALTER TABLE ALTER [COLUMN] <foo> SET */
1726 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
1727 Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
1728 COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
1729 /* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
1730 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
1731 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
1732 COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
1733 /* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
1734 else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
1735 Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
1736 COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
1737 /* ALTER TABLE ALTER [COLUMN] <foo> DROP */
1738 else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
1739 Matches8("ALTER", "TABLE", MatchAny, "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
1740 COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
1741 else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
1742 COMPLETE_WITH_CONST("ON");
1743 else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
1745 completion_info_charp = prev3_wd;
1746 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1748 /* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
1749 else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
1750 COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
1754 * If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
1757 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
1758 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
1759 /* If we have ALTER TABLE <sth> SET WITH provide OIDS */
1760 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
1761 COMPLETE_WITH_CONST("OIDS");
1762 /* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
1763 else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
1764 COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
1765 /* ALTER TABLE <foo> RESET */
1766 else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
1767 COMPLETE_WITH_CONST("(");
1768 /* ALTER TABLE <foo> SET|RESET ( */
1769 else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
1771 static const char *const list_TABLEOPTIONS[] =
1773 "autovacuum_analyze_scale_factor",
1774 "autovacuum_analyze_threshold",
1775 "autovacuum_enabled",
1776 "autovacuum_freeze_max_age",
1777 "autovacuum_freeze_min_age",
1778 "autovacuum_freeze_table_age",
1779 "autovacuum_multixact_freeze_max_age",
1780 "autovacuum_multixact_freeze_min_age",
1781 "autovacuum_multixact_freeze_table_age",
1782 "autovacuum_vacuum_cost_delay",
1783 "autovacuum_vacuum_cost_limit",
1784 "autovacuum_vacuum_scale_factor",
1785 "autovacuum_vacuum_threshold",
1788 "log_autovacuum_min_duration",
1789 "toast.autovacuum_enabled",
1790 "toast.autovacuum_freeze_max_age",
1791 "toast.autovacuum_freeze_min_age",
1792 "toast.autovacuum_freeze_table_age",
1793 "toast.autovacuum_multixact_freeze_max_age",
1794 "toast.autovacuum_multixact_freeze_min_age",
1795 "toast.autovacuum_multixact_freeze_table_age",
1796 "toast.autovacuum_vacuum_cost_delay",
1797 "toast.autovacuum_vacuum_cost_limit",
1798 "toast.autovacuum_vacuum_scale_factor",
1799 "toast.autovacuum_vacuum_threshold",
1800 "toast.log_autovacuum_min_duration",
1801 "user_catalog_table",
1805 COMPLETE_WITH_LIST(list_TABLEOPTIONS);
1807 else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
1809 completion_info_charp = prev5_wd;
1810 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1812 else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
1813 COMPLETE_WITH_CONST("INDEX");
1814 else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
1815 COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
1816 else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
1817 COMPLETE_WITH_CONST("IDENTITY");
1819 /* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
1820 else if (Matches3("ALTER", "TABLESPACE", MatchAny))
1821 COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
1822 /* ALTER TABLESPACE <foo> SET|RESET */
1823 else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
1824 COMPLETE_WITH_CONST("(");
1825 /* ALTER TABLESPACE <foo> SET|RESET ( */
1826 else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
1827 COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
1828 "effective_io_concurrency");
1830 /* ALTER TEXT SEARCH */
1831 else if (Matches3("ALTER", "TEXT", "SEARCH"))
1832 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1833 else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
1834 COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
1835 else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
1836 COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
1837 else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
1838 COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING",
1840 "OWNER TO", "RENAME TO", "SET SCHEMA");
1842 /* complete ALTER TYPE <foo> with actions */
1843 else if (Matches3("ALTER", "TYPE", MatchAny))
1844 COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
1846 "OWNER TO", "RENAME", "SET SCHEMA");
1847 /* complete ALTER TYPE <foo> ADD with actions */
1848 else if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
1849 COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
1850 /* ALTER TYPE <foo> RENAME */
1851 else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
1852 COMPLETE_WITH_LIST2("ATTRIBUTE", "TO");
1853 /* ALTER TYPE xxx RENAME ATTRIBUTE yyy */
1854 else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny))
1855 COMPLETE_WITH_CONST("TO");
1858 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
1861 else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
1862 COMPLETE_WITH_ATTR(prev3_wd, "");
1863 /* ALTER TYPE ALTER ATTRIBUTE <foo> */
1864 else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
1865 COMPLETE_WITH_CONST("TYPE");
1866 /* complete ALTER GROUP <foo> */
1867 else if (Matches3("ALTER", "GROUP", MatchAny))
1868 COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
1869 /* complete ALTER GROUP <foo> ADD|DROP with USER */
1870 else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
1871 COMPLETE_WITH_CONST("USER");
1872 /* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
1873 else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
1874 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
1876 /* BEGIN, END, ABORT */
1877 else if (Matches1("BEGIN|END|ABORT"))
1878 COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
1880 else if (Matches1("COMMIT"))
1881 COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
1882 /* RELEASE SAVEPOINT */
1883 else if (Matches1("RELEASE"))
1884 COMPLETE_WITH_CONST("SAVEPOINT");
1886 else if (Matches1("ROLLBACK"))
1887 COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
1889 else if (Matches1("CLUSTER"))
1890 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
1891 else if (Matches2("CLUSTER", "VERBOSE"))
1892 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
1893 /* If we have CLUSTER <sth>, then add "USING" */
1894 else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
1895 COMPLETE_WITH_CONST("USING");
1896 /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
1897 else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
1898 COMPLETE_WITH_CONST("USING");
1899 /* If we have CLUSTER <sth> USING, then add the index as well */
1900 else if (Matches3("CLUSTER", MatchAny, "USING") ||
1901 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
1903 completion_info_charp = prev2_wd;
1904 COMPLETE_WITH_QUERY(Query_for_index_of_table);
1908 else if (Matches1("COMMENT"))
1909 COMPLETE_WITH_CONST("ON");
1910 else if (Matches2("COMMENT", "ON"))
1912 static const char *const list_COMMENT[] =
1913 {"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION",
1914 "FOREIGN DATA WRAPPER", "FOREIGN TABLE",
1915 "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE",
1916 "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION",
1917 "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT",
1918 "TABLESPACE", "TEXT SEARCH", "ROLE", NULL};
1920 COMPLETE_WITH_LIST(list_COMMENT);
1922 else if (Matches3("COMMENT", "ON", "FOREIGN"))
1923 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
1924 else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
1925 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
1926 else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
1927 COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
1928 else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
1929 COMPLETE_WITH_CONST("ON");
1930 else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
1932 completion_info_charp = prev2_wd;
1933 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
1935 else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
1936 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
1937 else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
1938 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
1939 else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
1940 Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
1941 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
1942 COMPLETE_WITH_CONST("IS");
1947 * If we have COPY, offer list of tables or "(" (Also cover the analogous
1948 * backslash command).
1950 else if (Matches1("COPY|\\copy"))
1951 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1952 " UNION ALL SELECT '('");
1953 /* If we have COPY BINARY, complete with list of tables */
1954 else if (Matches2("COPY", "BINARY"))
1955 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1956 /* If we have COPY (, complete it with legal commands */
1957 else if (Matches2("COPY|\\copy", "("))
1958 COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
1959 /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
1960 else if (Matches2("COPY|\\copy", MatchAny) ||
1961 Matches3("COPY", "BINARY", MatchAny))
1962 COMPLETE_WITH_LIST2("FROM", "TO");
1963 /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
1964 else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
1965 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
1967 completion_charp = "";
1968 matches = completion_matches(text, complete_from_files);
1971 /* Handle COPY [BINARY] <sth> FROM|TO filename */
1972 else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
1973 Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
1974 COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
1977 /* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
1978 else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
1979 Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
1980 COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
1983 /* CREATE ACCESS METHOD */
1984 /* Complete "CREATE ACCESS METHOD <name>" */
1985 else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
1986 COMPLETE_WITH_CONST("TYPE");
1987 /* Complete "CREATE ACCESS METHOD <name> TYPE" */
1988 else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
1989 COMPLETE_WITH_CONST("INDEX");
1990 /* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
1991 else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
1992 COMPLETE_WITH_CONST("HANDLER");
1994 /* CREATE DATABASE */
1995 else if (Matches3("CREATE", "DATABASE", MatchAny))
1996 COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
1998 "ALLOW_CONNECTIONS", "CONNECTION LIMIT",
1999 "LC_COLLATE", "LC_CTYPE");
2001 else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
2002 COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
2004 /* CREATE EXTENSION */
2005 /* Complete with available extensions rather than installed ones. */
2006 else if (Matches2("CREATE", "EXTENSION"))
2007 COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
2008 /* CREATE EXTENSION <name> */
2009 else if (Matches3("CREATE", "EXTENSION", MatchAny))
2010 COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
2011 /* CREATE EXTENSION <name> VERSION */
2012 else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
2014 completion_info_charp = prev2_wd;
2015 COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
2018 /* CREATE FOREIGN */
2019 else if (Matches2("CREATE", "FOREIGN"))
2020 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2022 /* CREATE FOREIGN DATA WRAPPER */
2023 else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2024 COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
2026 /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
2027 /* First off we complete CREATE UNIQUE with "INDEX" */
2028 else if (TailMatches2("CREATE", "UNIQUE"))
2029 COMPLETE_WITH_CONST("INDEX");
2030 /* If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY",
2031 and existing indexes */
2032 else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
2033 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2034 " UNION SELECT 'ON'"
2035 " UNION SELECT 'CONCURRENTLY'");
2036 /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
2037 else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
2038 TailMatches2("INDEX|CONCURRENTLY", "ON"))
2039 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2040 /* Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing indexes */
2041 else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
2042 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2043 " UNION SELECT 'ON'");
2044 /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
2045 else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
2046 TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
2047 COMPLETE_WITH_CONST("ON");
2050 * Complete INDEX <name> ON <table> with a list of table columns (which
2051 * should really be in parens)
2053 else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
2054 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
2055 COMPLETE_WITH_LIST2("(", "USING");
2056 else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
2057 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
2058 COMPLETE_WITH_ATTR(prev2_wd, "");
2059 /* same if you put in USING */
2060 else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
2061 COMPLETE_WITH_ATTR(prev4_wd, "");
2062 /* Complete USING with an index method */
2063 else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
2064 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
2065 TailMatches4("INDEX", "ON", MatchAny, "USING"))
2066 COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
2067 else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
2068 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
2069 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
2070 COMPLETE_WITH_CONST("(");
2073 /* Complete "CREATE POLICY <name> ON" */
2074 else if (Matches3("CREATE", "POLICY", MatchAny))
2075 COMPLETE_WITH_CONST("ON");
2076 /* Complete "CREATE POLICY <name> ON <table>" */
2077 else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
2078 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2079 /* Complete "CREATE POLICY <name> ON <table> FOR|TO|USING|WITH CHECK" */
2080 else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
2081 COMPLETE_WITH_LIST4("FOR", "TO", "USING (", "WITH CHECK (");
2082 /* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
2083 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
2084 COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
2085 /* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
2086 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
2087 COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
2088 /* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
2089 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
2090 COMPLETE_WITH_LIST2("TO", "USING (");
2091 /* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
2092 else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
2093 COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
2094 /* Complete "CREATE POLICY <name> ON <table> TO <role>" */
2095 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
2096 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2097 /* Complete "CREATE POLICY <name> ON <table> USING (" */
2098 else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
2099 COMPLETE_WITH_CONST("(");
2102 /* Complete "CREATE RULE <sth>" with "AS ON" */
2103 else if (Matches3("CREATE", "RULE", MatchAny))
2104 COMPLETE_WITH_CONST("AS ON");
2105 /* Complete "CREATE RULE <sth> AS" with "ON" */
2106 else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
2107 COMPLETE_WITH_CONST("ON");
2108 /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
2109 else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
2110 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
2111 /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
2112 else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
2113 COMPLETE_WITH_CONST("TO");
2114 /* Complete "AS ON <sth> TO" with a table name */
2115 else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
2116 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2118 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2119 else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
2120 TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
2121 COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
2122 "CYCLE", "OWNED BY", "START WITH");
2123 else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
2124 TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
2125 COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
2127 /* CREATE SERVER <name> */
2128 else if (Matches3("CREATE", "SERVER", MatchAny))
2129 COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
2131 /* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2132 /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
2133 else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
2134 COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
2135 /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
2136 else if (TailMatches2("CREATE", "UNLOGGED"))
2137 COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
2139 /* CREATE TABLESPACE */
2140 else if (Matches3("CREATE", "TABLESPACE", MatchAny))
2141 COMPLETE_WITH_LIST2("OWNER", "LOCATION");
2142 /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
2143 else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
2144 COMPLETE_WITH_CONST("LOCATION");
2146 /* CREATE TEXT SEARCH */
2147 else if (Matches3("CREATE", "TEXT", "SEARCH"))
2148 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2149 else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
2150 COMPLETE_WITH_CONST("(");
2152 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
2153 /* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
2154 else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
2155 COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
2156 /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
2157 else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
2158 COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
2159 /* complete CREATE TRIGGER <name> INSTEAD OF with an event */
2160 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
2161 COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
2162 /* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
2163 else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
2164 TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
2165 COMPLETE_WITH_LIST2("ON", "OR");
2168 * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
2171 else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
2172 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2173 /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
2174 else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
2175 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2176 /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
2177 else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
2178 COMPLETE_WITH_CONST("PROCEDURE");
2180 /* CREATE ROLE,USER,GROUP <name> */
2181 else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
2182 !TailMatches2("USER", "MAPPING"))
2184 static const char *const list_CREATEROLE[] =
2185 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2186 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2187 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2188 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2189 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2190 "VALID UNTIL", "WITH", NULL};
2192 COMPLETE_WITH_LIST(list_CREATEROLE);
2195 /* CREATE ROLE,USER,GROUP <name> WITH */
2196 else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
2198 /* Similar to the above, but don't complete "WITH" again. */
2199 static const char *const list_CREATEROLE_WITH[] =
2200 {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
2201 "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
2202 "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
2203 "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
2204 "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
2205 "VALID UNTIL", NULL};
2207 COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
2211 * complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
2214 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
2215 COMPLETE_WITH_CONST("PASSWORD");
2216 /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
2217 else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
2218 COMPLETE_WITH_LIST2("GROUP", "ROLE");
2220 /* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
2221 /* Complete CREATE VIEW <name> with AS */
2222 else if (TailMatches3("CREATE", "VIEW", MatchAny))
2223 COMPLETE_WITH_CONST("AS");
2224 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
2225 else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
2226 COMPLETE_WITH_CONST("SELECT");
2228 /* CREATE MATERIALIZED VIEW */
2229 else if (Matches2("CREATE", "MATERIALIZED"))
2230 COMPLETE_WITH_CONST("VIEW");
2231 /* Complete CREATE MATERIALIZED VIEW <name> with AS */
2232 else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
2233 COMPLETE_WITH_CONST("AS");
2234 /* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
2235 else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
2236 COMPLETE_WITH_CONST("SELECT");
2238 /* CREATE EVENT TRIGGER */
2239 else if (Matches2("CREATE", "EVENT"))
2240 COMPLETE_WITH_CONST("TRIGGER");
2241 /* Complete CREATE EVENT TRIGGER <name> with ON */
2242 else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
2243 COMPLETE_WITH_CONST("ON");
2244 /* Complete CREATE EVENT TRIGGER <name> ON with event_type */
2245 else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
2246 COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
2249 else if (Matches2("DECLARE", MatchAny))
2250 COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
2252 else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
2253 COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
2255 /* DELETE --- can be inside EXPLAIN, RULE, etc */
2256 /* ... despite which, only complete DELETE with FROM at start of line */
2257 else if (Matches1("DELETE"))
2258 COMPLETE_WITH_CONST("FROM");
2259 /* Complete DELETE FROM with a list of tables */
2260 else if (TailMatches2("DELETE", "FROM"))
2261 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2262 /* Complete DELETE FROM <table> */
2263 else if (TailMatches3("DELETE", "FROM", MatchAny))
2264 COMPLETE_WITH_LIST2("USING", "WHERE");
2265 /* XXX: implement tab completion for DELETE ... USING */
2268 else if (Matches1("DISCARD"))
2269 COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
2272 else if (Matches1("DO"))
2273 COMPLETE_WITH_CONST("LANGUAGE");
2276 /* Complete DROP object with CASCADE / RESTRICT */
2277 else if (Matches3("DROP",
2278 "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
2280 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
2281 (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
2282 ends_with(prev_wd, ')')) ||
2283 Matches4("DROP", "EVENT", "TRIGGER", MatchAny) ||
2284 Matches5("DROP", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
2285 Matches4("DROP", "FOREIGN", "TABLE", MatchAny) ||
2286 Matches5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", MatchAny))
2287 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2289 /* help completing some of the variants */
2290 else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
2291 COMPLETE_WITH_CONST("(");
2292 else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
2293 COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
2294 else if (Matches2("DROP", "FOREIGN"))
2295 COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
2298 else if (Matches2("DROP", "INDEX"))
2299 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
2300 " UNION SELECT 'CONCURRENTLY'");
2301 else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
2302 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2303 else if (Matches3("DROP", "INDEX", MatchAny))
2304 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2305 else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
2306 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2308 /* DROP MATERIALIZED VIEW */
2309 else if (Matches2("DROP", "MATERIALIZED"))
2310 COMPLETE_WITH_CONST("VIEW");
2311 else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
2312 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2315 else if (Matches2("DROP", "OWNED"))
2316 COMPLETE_WITH_CONST("BY");
2317 else if (Matches3("DROP", "OWNED", "BY"))
2318 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2320 else if (Matches3("DROP", "TEXT", "SEARCH"))
2321 COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
2324 else if (Matches3("DROP", "TRIGGER", MatchAny))
2325 COMPLETE_WITH_CONST("ON");
2326 else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
2328 completion_info_charp = prev2_wd;
2329 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
2331 else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
2332 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2334 /* DROP EVENT TRIGGER */
2335 else if (Matches2("DROP", "EVENT"))
2336 COMPLETE_WITH_CONST("TRIGGER");
2337 else if (Matches3("DROP", "EVENT", "TRIGGER"))
2338 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2340 /* DROP POLICY <name> */
2341 else if (Matches2("DROP", "POLICY"))
2342 COMPLETE_WITH_QUERY(Query_for_list_of_policies);
2343 /* DROP POLICY <name> ON */
2344 else if (Matches3("DROP", "POLICY", MatchAny))
2345 COMPLETE_WITH_CONST("ON");
2346 /* DROP POLICY <name> ON <table> */
2347 else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
2349 completion_info_charp = prev2_wd;
2350 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
2354 else if (Matches3("DROP", "RULE", MatchAny))
2355 COMPLETE_WITH_CONST("ON");
2356 else if (Matches4("DROP", "RULE", MatchAny, "ON"))
2358 completion_info_charp = prev2_wd;
2359 COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
2361 else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
2362 COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
2365 else if (Matches1("EXECUTE"))
2366 COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
2371 * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
2373 else if (Matches1("EXPLAIN"))
2374 COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2375 "ANALYZE", "VERBOSE");
2376 else if (Matches2("EXPLAIN", "ANALYZE"))
2377 COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
2379 else if (Matches2("EXPLAIN", "VERBOSE") ||
2380 Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
2381 COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
2384 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
2385 else if (Matches1("FETCH|MOVE"))
2386 COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
2387 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
2388 else if (Matches2("FETCH|MOVE", MatchAny))
2389 COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
2392 * Complete FETCH <sth1> <sth2> with "FROM" or "IN". These are equivalent,
2393 * but we may as well tab-complete both: perhaps some users prefer one
2394 * variant or the other.
2396 else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
2397 COMPLETE_WITH_LIST2("FROM", "IN");
2399 /* FOREIGN DATA WRAPPER */
2400 /* applies in ALTER/DROP FDW and in CREATE SERVER */
2401 else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
2402 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
2403 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2404 /* applies in CREATE SERVER */
2405 else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
2406 HeadMatches2("CREATE", "SERVER"))
2407 COMPLETE_WITH_CONST("OPTIONS");
2410 else if (TailMatches2("FOREIGN", "TABLE") &&
2411 !TailMatches3("CREATE", MatchAny, MatchAny))
2412 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2414 /* FOREIGN SERVER */
2415 else if (TailMatches2("FOREIGN", "SERVER"))
2416 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2418 /* GRANT && REVOKE --- is allowed inside CREATE SCHEMA, so use TailMatches */
2419 /* Complete GRANT/REVOKE with a list of roles and privileges */
2420 else if (TailMatches1("GRANT|REVOKE"))
2421 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2422 " UNION SELECT 'SELECT'"
2423 " UNION SELECT 'INSERT'"
2424 " UNION SELECT 'UPDATE'"
2425 " UNION SELECT 'DELETE'"
2426 " UNION SELECT 'TRUNCATE'"
2427 " UNION SELECT 'REFERENCES'"
2428 " UNION SELECT 'TRIGGER'"
2429 " UNION SELECT 'CREATE'"
2430 " UNION SELECT 'CONNECT'"
2431 " UNION SELECT 'TEMPORARY'"
2432 " UNION SELECT 'EXECUTE'"
2433 " UNION SELECT 'USAGE'"
2434 " UNION SELECT 'ALL'");
2437 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
2440 else if (TailMatches2("GRANT|REVOKE", MatchAny))
2442 if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
2443 COMPLETE_WITH_CONST("ON");
2444 else if (TailMatches2("GRANT", MatchAny))
2445 COMPLETE_WITH_CONST("TO");
2447 COMPLETE_WITH_CONST("FROM");
2451 * Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
2454 * Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to query
2455 * result via UNION; seems to work intuitively.
2457 * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
2458 * here will only work if the privilege list contains exactly one
2461 else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
2462 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
2463 " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
2464 " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
2465 " UNION SELECT 'ALL TABLES IN SCHEMA'"
2466 " UNION SELECT 'DATABASE'"
2467 " UNION SELECT 'DOMAIN'"
2468 " UNION SELECT 'FOREIGN DATA WRAPPER'"
2469 " UNION SELECT 'FOREIGN SERVER'"
2470 " UNION SELECT 'FUNCTION'"
2471 " UNION SELECT 'LANGUAGE'"
2472 " UNION SELECT 'LARGE OBJECT'"
2473 " UNION SELECT 'SCHEMA'"
2474 " UNION SELECT 'SEQUENCE'"
2475 " UNION SELECT 'TABLE'"
2476 " UNION SELECT 'TABLESPACE'"
2477 " UNION SELECT 'TYPE'");
2479 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
2480 COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
2481 "TABLES IN SCHEMA");
2483 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
2484 COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
2487 * Complete "GRANT/REVOKE * ON DATABASE/DOMAIN/..." with a list of
2488 * appropriate objects.
2490 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
2492 else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
2494 if (TailMatches1("DATABASE"))
2495 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2496 else if (TailMatches1("DOMAIN"))
2497 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2498 else if (TailMatches1("FUNCTION"))
2499 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2500 else if (TailMatches1("LANGUAGE"))
2501 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2502 else if (TailMatches1("SCHEMA"))
2503 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2504 else if (TailMatches1("SEQUENCE"))
2505 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2506 else if (TailMatches1("TABLE"))
2507 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2508 else if (TailMatches1("TABLESPACE"))
2509 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2510 else if (TailMatches1("TYPE"))
2511 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2512 else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
2513 COMPLETE_WITH_CONST("TO");
2515 COMPLETE_WITH_CONST("FROM");
2519 * Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
2520 * CURRENT_USER, or SESSION_USER.
2522 else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
2523 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
2524 COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
2526 /* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
2527 else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
2528 COMPLETE_WITH_CONST("TO");
2529 else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
2530 COMPLETE_WITH_CONST("FROM");
2532 /* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
2533 else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
2535 if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2536 COMPLETE_WITH_CONST("TO");
2538 COMPLETE_WITH_CONST("FROM");
2541 /* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
2542 else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
2544 if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2545 COMPLETE_WITH_CONST("TO");
2547 COMPLETE_WITH_CONST("FROM");
2550 /* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
2551 else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
2553 if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
2554 COMPLETE_WITH_CONST("TO");
2556 COMPLETE_WITH_CONST("FROM");
2560 else if (TailMatches3("FROM", MatchAny, "GROUP"))
2561 COMPLETE_WITH_CONST("BY");
2563 /* IMPORT FOREIGN SCHEMA */
2564 else if (Matches1("IMPORT"))
2565 COMPLETE_WITH_CONST("FOREIGN SCHEMA");
2566 else if (Matches2("IMPORT", "FOREIGN"))
2567 COMPLETE_WITH_CONST("SCHEMA");
2569 /* INSERT --- can be inside EXPLAIN, RULE, etc */
2570 /* Complete INSERT with "INTO" */
2571 else if (TailMatches1("INSERT"))
2572 COMPLETE_WITH_CONST("INTO");
2573 /* Complete INSERT INTO with table names */
2574 else if (TailMatches2("INSERT", "INTO"))
2575 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2576 /* Complete "INSERT INTO <table> (" with attribute names */
2577 else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
2578 COMPLETE_WITH_ATTR(prev2_wd, "");
2581 * Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
2582 * "TABLE" or "DEFAULT VALUES"
2584 else if (TailMatches3("INSERT", "INTO", MatchAny))
2585 COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
2588 * Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
2591 else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
2592 ends_with(prev_wd, ')'))
2593 COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
2595 /* Insert an open parenthesis after "VALUES" */
2596 else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
2597 COMPLETE_WITH_CONST("(");
2600 /* Complete LOCK [TABLE] with a list of tables */
2601 else if (Matches1("LOCK"))
2602 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
2603 " UNION SELECT 'TABLE'");
2604 else if (Matches2("LOCK", "TABLE"))
2605 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
2607 /* For the following, handle the case of a single table only for now */
2609 /* Complete LOCK [TABLE] <table> with "IN" */
2610 else if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
2611 Matches3("LOCK", "TABLE", MatchAny))
2612 COMPLETE_WITH_CONST("IN");
2614 /* Complete LOCK [TABLE] <table> IN with a lock mode */
2615 else if (Matches3("LOCK", MatchAny, "IN") ||
2616 Matches4("LOCK", "TABLE", MatchAny, "IN"))
2617 COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
2618 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
2619 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
2620 "SHARE ROW EXCLUSIVE MODE",
2621 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
2623 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
2624 else if (TailMatches1("NOTIFY"))
2625 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'");
2628 else if (TailMatches1("OPTIONS"))
2629 COMPLETE_WITH_CONST("(");
2631 /* OWNER TO - complete with available roles */
2632 else if (TailMatches2("OWNER", "TO"))
2633 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2636 else if (TailMatches3("FROM", MatchAny, "ORDER"))
2637 COMPLETE_WITH_CONST("BY");
2638 else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
2639 COMPLETE_WITH_ATTR(prev3_wd, "");
2642 else if (Matches3("PREPARE", MatchAny, "AS"))
2643 COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
2646 * PREPARE TRANSACTION is missing on purpose. It's intended for transaction
2647 * managers, not for manual use in interactive sessions.
2650 /* REASSIGN OWNED BY xxx TO yyy */
2651 else if (Matches1("REASSIGN"))
2652 COMPLETE_WITH_CONST("OWNED BY");
2653 else if (Matches2("REASSIGN", "OWNED"))
2654 COMPLETE_WITH_CONST("BY");
2655 else if (Matches3("REASSIGN", "OWNED", "BY"))
2656 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2657 else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
2658 COMPLETE_WITH_CONST("TO");
2659 else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
2660 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2662 /* REFRESH MATERIALIZED VIEW */
2663 else if (Matches1("REFRESH"))
2664 COMPLETE_WITH_CONST("MATERIALIZED VIEW");
2665 else if (Matches2("REFRESH", "MATERIALIZED"))
2666 COMPLETE_WITH_CONST("VIEW");
2667 else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
2668 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
2669 " UNION SELECT 'CONCURRENTLY'");
2670 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
2671 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2672 else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
2673 COMPLETE_WITH_CONST("WITH");
2674 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
2675 COMPLETE_WITH_CONST("WITH");
2676 else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
2677 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2678 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
2679 COMPLETE_WITH_LIST2("NO DATA", "DATA");
2680 else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
2681 COMPLETE_WITH_CONST("DATA");
2682 else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
2683 COMPLETE_WITH_CONST("DATA");
2686 else if (Matches1("REINDEX"))
2687 COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
2688 else if (Matches2("REINDEX", "TABLE"))
2689 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2690 else if (Matches2("REINDEX", "INDEX"))
2691 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2692 else if (Matches2("REINDEX", "SCHEMA"))
2693 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2694 else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
2695 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2697 /* SECURITY LABEL */
2698 else if (Matches1("SECURITY"))
2699 COMPLETE_WITH_CONST("LABEL");
2700 else if (Matches2("SECURITY", "LABEL"))
2701 COMPLETE_WITH_LIST2("ON", "FOR");
2702 else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
2703 COMPLETE_WITH_CONST("ON");
2704 else if (Matches3("SECURITY", "LABEL", "ON") ||
2705 Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
2707 static const char *const list_SECURITY_LABEL[] =
2708 {"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
2709 "EVENT TRIGGER", "FOREIGN TABLE", "FUNCTION", "LARGE OBJECT",
2710 "MATERIALIZED VIEW", "LANGUAGE", "ROLE", "SCHEMA",
2711 "SEQUENCE", "TABLESPACE", "TYPE", "VIEW", NULL};
2713 COMPLETE_WITH_LIST(list_SECURITY_LABEL);
2715 else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
2716 COMPLETE_WITH_CONST("IS");
2721 /* SET, RESET, SHOW */
2722 /* Complete with a variable name */
2723 else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
2724 COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
2725 else if (Matches1("SHOW"))
2726 COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
2727 /* Complete "SET TRANSACTION" */
2728 else if (Matches2("SET|BEGIN|START", "TRANSACTION") ||
2729 Matches2("BEGIN", "WORK") ||
2730 Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
2731 COMPLETE_WITH_LIST2("ISOLATION LEVEL", "READ");
2732 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
2733 Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
2734 COMPLETE_WITH_CONST("LEVEL");
2735 else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL"))
2736 COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
2737 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ"))
2738 COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
2739 else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE"))
2740 COMPLETE_WITH_CONST("READ");
2741 else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ"))
2742 COMPLETE_WITH_LIST2("ONLY", "WRITE");
2743 /* SET CONSTRAINTS */
2744 else if (Matches2("SET", "CONSTRAINTS"))
2745 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
2746 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
2747 else if (Matches3("SET", "CONSTRAINTS", MatchAny))
2748 COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
2749 /* Complete SET ROLE */
2750 else if (Matches2("SET", "ROLE"))
2751 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2752 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
2753 else if (Matches2("SET", "SESSION"))
2754 COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
2755 /* Complete SET SESSION AUTHORIZATION with username */
2756 else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
2757 COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
2758 /* Complete RESET SESSION with AUTHORIZATION */
2759 else if (Matches2("RESET", "SESSION"))
2760 COMPLETE_WITH_CONST("AUTHORIZATION");
2761 /* Complete SET <var> with "TO" */
2762 else if (Matches2("SET", MatchAny))
2763 COMPLETE_WITH_CONST("TO");
2764 /* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
2765 else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
2766 TailMatches2("SET", MatchAny))
2767 COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
2768 /* Suggest possible variable values */
2769 else if (TailMatches3("SET", MatchAny, "TO|="))
2771 /* special cased code for individual GUCs */
2772 if (TailMatches2("DateStyle", "TO|="))
2774 static const char *const my_list[] =
2775 {"ISO", "SQL", "Postgres", "German",
2776 "YMD", "DMY", "MDY",
2777 "US", "European", "NonEuropean",
2780 COMPLETE_WITH_LIST(my_list);
2782 else if (TailMatches2("search_path", "TO|="))
2783 COMPLETE_WITH_QUERY(Query_for_list_of_schemas
2784 " AND nspname not like 'pg\\_toast%%' "
2785 " AND nspname not like 'pg\\_temp%%' "
2786 " UNION SELECT 'DEFAULT' ");
2789 /* generic, type based, GUC support */
2790 char *guctype = get_guctype(prev2_wd);
2792 if (guctype && strcmp(guctype, "enum") == 0)
2794 char querybuf[1024];
2796 snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
2797 COMPLETE_WITH_QUERY(querybuf);
2799 else if (guctype && strcmp(guctype, "bool") == 0)
2800 COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
2801 "1", "0", "DEFAULT");
2803 COMPLETE_WITH_CONST("DEFAULT");
2810 /* START TRANSACTION */
2811 else if (Matches1("START"))
2812 COMPLETE_WITH_CONST("TRANSACTION");
2814 /* TABLE, but not TABLE embedded in other commands */
2815 else if (Matches1("TABLE"))
2816 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
2819 else if (TailMatches1("TABLESAMPLE"))
2820 COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
2821 else if (TailMatches2("TABLESAMPLE", MatchAny))
2822 COMPLETE_WITH_CONST("(");
2825 else if (Matches1("TRUNCATE"))
2826 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2829 else if (Matches1("UNLISTEN"))
2830 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 '*'");
2832 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
2833 /* If prev. word is UPDATE suggest a list of tables */
2834 else if (TailMatches1("UPDATE"))
2835 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
2836 /* Complete UPDATE <table> with "SET" */
2837 else if (TailMatches2("UPDATE", MatchAny))
2838 COMPLETE_WITH_CONST("SET");
2839 /* Complete UPDATE <table> SET with list of attributes */
2840 else if (TailMatches3("UPDATE", MatchAny, "SET"))
2841 COMPLETE_WITH_ATTR(prev2_wd, "");
2842 /* UPDATE <table> SET <attr> = */
2843 else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
2844 COMPLETE_WITH_CONST("=");
2847 else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
2848 COMPLETE_WITH_CONST("FOR");
2849 else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
2850 COMPLETE_WITH_QUERY(Query_for_list_of_roles
2851 " UNION SELECT 'CURRENT_USER'"
2852 " UNION SELECT 'PUBLIC'"
2853 " UNION SELECT 'USER'");
2854 else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
2855 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
2856 else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
2857 COMPLETE_WITH_CONST("SERVER");
2858 else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
2859 COMPLETE_WITH_CONST("OPTIONS");
2862 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
2863 * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
2865 else if (Matches1("VACUUM"))
2866 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2867 " UNION SELECT 'FULL'"
2868 " UNION SELECT 'FREEZE'"
2869 " UNION SELECT 'ANALYZE'"
2870 " UNION SELECT 'VERBOSE'");
2871 else if (Matches2("VACUUM", "FULL|FREEZE"))
2872 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2873 " UNION SELECT 'ANALYZE'"
2874 " UNION SELECT 'VERBOSE'");
2875 else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
2876 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2877 " UNION SELECT 'VERBOSE'");
2878 else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
2879 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2880 " UNION SELECT 'ANALYZE'");
2881 else if (Matches2("VACUUM", "VERBOSE"))
2882 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2883 " UNION SELECT 'ANALYZE'");
2884 else if (Matches2("VACUUM", "ANALYZE"))
2885 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
2886 " UNION SELECT 'VERBOSE'");
2887 else if (HeadMatches1("VACUUM"))
2888 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
2890 /* WITH [RECURSIVE] */
2893 * Only match when WITH is the first word, as WITH may appear in many
2896 else if (Matches1("WITH"))
2897 COMPLETE_WITH_CONST("RECURSIVE");
2900 /* Complete with list of tables */
2901 else if (Matches1("ANALYZE"))
2902 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
2905 /* Simple case of the word before the where being the table name */
2906 else if (TailMatches2(MatchAny, "WHERE"))
2907 COMPLETE_WITH_ATTR(prev2_wd, "");
2910 /* TODO: also include SRF ? */
2911 else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
2912 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2915 else if (TailMatches1("JOIN"))
2916 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2918 /* Backslash commands */
2919 /* TODO: \dc \dd \dl */
2920 else if (TailMatchesCS1("\\?"))
2921 COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
2922 else if (TailMatchesCS1("\\connect|\\c"))
2924 if (!recognized_connection_string(text))
2925 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
2927 else if (TailMatchesCS2("\\connect|\\c", MatchAny))
2929 if (!recognized_connection_string(prev_wd))
2930 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2932 else if (TailMatchesCS1("\\da*"))
2933 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
2934 else if (TailMatchesCS1("\\db*"))
2935 COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
2936 else if (TailMatchesCS1("\\dD*"))
2937 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
2938 else if (TailMatchesCS1("\\des*"))
2939 COMPLETE_WITH_QUERY(Query_for_list_of_servers);
2940 else if (TailMatchesCS1("\\deu*"))
2941 COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
2942 else if (TailMatchesCS1("\\dew*"))
2943 COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
2944 else if (TailMatchesCS1("\\df*"))
2945 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2947 else if (TailMatchesCS1("\\dFd*"))
2948 COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
2949 else if (TailMatchesCS1("\\dFp*"))
2950 COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
2951 else if (TailMatchesCS1("\\dFt*"))
2952 COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
2953 /* must be at end of \dF alternatives: */
2954 else if (TailMatchesCS1("\\dF*"))
2955 COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
2957 else if (TailMatchesCS1("\\di*"))
2958 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
2959 else if (TailMatchesCS1("\\dL*"))
2960 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
2961 else if (TailMatchesCS1("\\dn*"))
2962 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
2963 else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
2964 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
2965 else if (TailMatchesCS1("\\ds*"))
2966 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
2967 else if (TailMatchesCS1("\\dt*"))
2968 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
2969 else if (TailMatchesCS1("\\dT*"))
2970 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
2971 else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
2972 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2973 else if (TailMatchesCS1("\\dv*"))
2974 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2975 else if (TailMatchesCS1("\\dx*"))
2976 COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
2977 else if (TailMatchesCS1("\\dm*"))
2978 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
2979 else if (TailMatchesCS1("\\dE*"))
2980 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
2981 else if (TailMatchesCS1("\\dy*"))
2982 COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
2984 /* must be at end of \d alternatives: */
2985 else if (TailMatchesCS1("\\d*"))
2986 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
2988 else if (TailMatchesCS1("\\ef"))
2989 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
2990 else if (TailMatchesCS1("\\ev"))
2991 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
2993 else if (TailMatchesCS1("\\encoding"))
2994 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
2995 else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
2996 COMPLETE_WITH_LIST(sql_commands);
2997 else if (TailMatchesCS1("\\password"))
2998 COMPLETE_WITH_QUERY(Query_for_list_of_roles);
2999 else if (TailMatchesCS1("\\pset"))
3001 static const char *const my_list[] =
3002 {"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
3003 "footer", "format", "linestyle", "null", "numericlocale",
3004 "pager", "recordsep", "recordsep_zero", "tableattr", "title",
3005 "tuples_only", "unicode_border_linestyle",
3006 "unicode_column_linestyle", "unicode_header_linestyle", NULL};
3008 COMPLETE_WITH_LIST_CS(my_list);
3010 else if (TailMatchesCS2("\\pset", MatchAny))
3012 if (TailMatchesCS1("format"))
3014 static const char *const my_list[] =
3015 {"unaligned", "aligned", "wrapped", "html", "asciidoc",
3016 "latex", "latex-longtable", "troff-ms", NULL};
3018 COMPLETE_WITH_LIST_CS(my_list);
3020 else if (TailMatchesCS1("linestyle"))
3021 COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
3022 else if (TailMatchesCS1("unicode_border_linestyle|"
3023 "unicode_column_linestyle|"
3024 "unicode_header_linestyle"))
3025 COMPLETE_WITH_LIST_CS2("single", "double");
3027 else if (TailMatchesCS1("\\unset"))
3029 matches = complete_from_variables(text, "", "", true);
3031 else if (TailMatchesCS1("\\set"))
3033 matches = complete_from_variables(text, "", "", false);
3035 else if (TailMatchesCS2("\\set", MatchAny))
3037 if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
3038 "SINGLELINE|SINGLESTEP"))
3039 COMPLETE_WITH_LIST_CS2("on", "off");
3040 else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
3041 COMPLETE_WITH_LIST_CS4("lower", "upper",
3042 "preserve-lower", "preserve-upper");
3043 else if (TailMatchesCS1("ECHO"))
3044 COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
3045 else if (TailMatchesCS1("ECHO_HIDDEN"))
3046 COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
3047 else if (TailMatchesCS1("HISTCONTROL"))
3048 COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
3049 "ignoreboth", "none");
3050 else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
3051 COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
3052 else if (TailMatchesCS1("SHOW_CONTEXT"))
3053 COMPLETE_WITH_LIST_CS3("never", "errors", "always");
3054 else if (TailMatchesCS1("VERBOSITY"))
3055 COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
3057 else if (TailMatchesCS1("\\sf*"))
3058 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
3059 else if (TailMatchesCS1("\\sv*"))
3060 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
3061 else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
3062 "\\ir|\\include_relative|\\o|\\out|"
3063 "\\s|\\w|\\write|\\lo_import"))
3065 completion_charp = "\\";
3066 matches = completion_matches(text, complete_from_files);
3070 * Finally, we look through the list of "things", such as TABLE, INDEX and
3071 * check if that was the previous word. If so, execute the query to get a
3078 for (i = 0; words_after_create[i].name; i++)
3080 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
3082 if (words_after_create[i].query)
3083 COMPLETE_WITH_QUERY(words_after_create[i].query);
3084 else if (words_after_create[i].squery)
3085 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
3093 * If we still don't have anything to match we have to fabricate some sort
3094 * of default list. If we were to just return NULL, readline automatically
3095 * attempts filename completion, and that's usually no good.
3097 if (matches == NULL)
3099 COMPLETE_WITH_CONST("");
3100 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
3101 rl_completion_append_character = '\0';
3106 free(previous_words);
3109 /* Return our Grand List O' Matches */
3115 * GENERATOR FUNCTIONS
3117 * These functions do all the actual work of completing the input. They get
3118 * passed the text so far and the count how many times they have been called
3119 * so far with the same text.
3120 * If you read the above carefully, you'll see that these don't get called
3121 * directly but through the readline interface.
3122 * The return value is expected to be the full completion of the text, going
3123 * through a list each time, or NULL if there are no more matches. The string
3124 * will be free()'d by readline, so you must run it through strdup() or
3125 * something of that sort.
3129 * Common routine for create_command_generator and drop_command_generator.
3130 * Entries that have 'excluded' flags are not returned.
3133 create_or_drop_command_generator(const char *text, int state, bits32 excluded)
3135 static int list_index,
3139 /* If this is the first time for this completion, init some values */
3143 string_length = strlen(text);
3146 /* find something that matches */
3147 while ((name = words_after_create[list_index++].name))
3149 if ((pg_strncasecmp(name, text, string_length) == 0) &&
3150 !(words_after_create[list_index - 1].flags & excluded))
3151 return pg_strdup_keyword_case(name, text);
3153 /* if nothing matches, return NULL */
3158 * This one gives you one from a list of things you can put after CREATE
3162 create_command_generator(const char *text, int state)
3164 return create_or_drop_command_generator(text, state, THING_NO_CREATE);
3168 * This function gives you a list of things you can put after a DROP command.
3171 drop_command_generator(const char *text, int state)
3173 return create_or_drop_command_generator(text, state, THING_NO_DROP);
3176 /* The following two functions are wrappers for _complete_from_query */
3179 complete_from_query(const char *text, int state)
3181 return _complete_from_query(0, text, state);
3185 complete_from_schema_query(const char *text, int state)
3187 return _complete_from_query(1, text, state);
3192 * This creates a list of matching things, according to a query pointed to
3193 * by completion_charp.
3194 * The query can be one of two kinds:
3196 * 1. A simple query which must contain a %d and a %s, which will be replaced
3197 * by the string length of the text and the text itself. The query may also
3198 * have up to four more %s in it; the first two such will be replaced by the
3199 * value of completion_info_charp, the next two by the value of
3200 * completion_info_charp2.
3202 * 2. A schema query used for completion of both schema and relation names.
3203 * These are more complex and must contain in the following order:
3204 * %d %s %d %s %d %s %s %d %s
3205 * where %d is the string length of the text and %s the text itself.
3207 * It is assumed that strings should be escaped to become SQL literals
3208 * (that is, what is in the query is actually ... '%s' ...)
3210 * See top of file for examples of both kinds of query.
3213 _complete_from_query(int is_schema_query, const char *text, int state)
3215 static int list_index,
3217 static PGresult *result = NULL;
3219 * If this is the first time for this completion, we fetch a list of our
3220 * "things" from the backend.
3224 PQExpBufferData query_buffer;
3227 char *e_info_charp2;
3228 const char *pstr = text;
3229 int char_length = 0;
3232 byte_length = strlen(text);
3234 /* Count length as number of characters (not bytes), for passing to substring */
3238 pstr += PQmblen(pstr, pset.encoding);
3241 /* Free any prior result */
3245 /* Set up suitably-escaped copies of textual inputs */
3246 e_text = escape_string(text);
3248 if (completion_info_charp)
3249 e_info_charp = escape_string(completion_info_charp);
3251 e_info_charp = NULL;
3253 if (completion_info_charp2)
3254 e_info_charp2 = escape_string(completion_info_charp2);
3256 e_info_charp2 = NULL;
3258 initPQExpBuffer(&query_buffer);
3260 if (is_schema_query)
3262 /* completion_squery gives us the pieces to assemble */
3263 const char *qualresult = completion_squery->qualresult;
3265 if (qualresult == NULL)
3266 qualresult = completion_squery->result;
3268 /* Get unqualified names matching the input-so-far */
3269 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
3270 completion_squery->result,
3271 completion_squery->catname);
3272 if (completion_squery->selcondition)
3273 appendPQExpBuffer(&query_buffer, "%s AND ",
3274 completion_squery->selcondition);
3275 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
3276 completion_squery->result,
3277 char_length, e_text);
3278 appendPQExpBuffer(&query_buffer, " AND %s",
3279 completion_squery->viscondition);
3282 * When fetching relation names, suppress system catalogs unless
3283 * the input-so-far begins with "pg_". This is a compromise
3284 * between not offering system catalogs for completion at all, and
3285 * having them swamp the result when the input is just "p".
3287 if (strcmp(completion_squery->catname,
3288 "pg_catalog.pg_class c") == 0 &&
3289 strncmp(text, "pg_", 3) !=0)
3291 appendPQExpBufferStr(&query_buffer,
3292 " AND c.relnamespace <> (SELECT oid FROM"
3293 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
3297 * Add in matching schema names, but only if there is more than
3298 * one potential match among schema names.
3300 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3301 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
3302 "FROM pg_catalog.pg_namespace n "
3303 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
3304 char_length, e_text);
3305 appendPQExpBuffer(&query_buffer,
3306 " AND (SELECT pg_catalog.count(*)"
3307 " FROM pg_catalog.pg_namespace"
3308 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3309 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
3310 char_length, e_text);
3313 * Add in matching qualified names, but only if there is exactly
3314 * one schema matching the input-so-far.
3316 appendPQExpBuffer(&query_buffer, "\nUNION\n"
3317 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
3318 "FROM %s, pg_catalog.pg_namespace n "
3319 "WHERE %s = n.oid AND ",
3321 completion_squery->catname,
3322 completion_squery->namespace);
3323 if (completion_squery->selcondition)
3324 appendPQExpBuffer(&query_buffer, "%s AND ",
3325 completion_squery->selcondition);
3326 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
3328 char_length, e_text);
3331 * This condition exploits the single-matching-schema rule to
3332 * speed up the query
3334 appendPQExpBuffer(&query_buffer,
3335 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
3336 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
3337 char_length, e_text);
3338 appendPQExpBuffer(&query_buffer,
3339 " AND (SELECT pg_catalog.count(*)"
3340 " FROM pg_catalog.pg_namespace"
3341 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
3342 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
3343 char_length, e_text);
3345 /* If an addon query was provided, use it */
3346 if (completion_charp)
3347 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
3351 /* completion_charp is an sprintf-style format string */
3352 appendPQExpBuffer(&query_buffer, completion_charp,
3353 char_length, e_text,
3354 e_info_charp, e_info_charp,
3355 e_info_charp2, e_info_charp2);
3358 /* Limit the number of records in the result */
3359 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
3360 completion_max_records);
3362 result = exec_query(query_buffer.data);
3364 termPQExpBuffer(&query_buffer);
3369 free(e_info_charp2);
3372 /* Find something that matches */
3373 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
3377 while (list_index < PQntuples(result) &&
3378 (item = PQgetvalue(result, list_index++, 0)))
3379 if (pg_strncasecmp(text, item, byte_length) == 0)
3380 return pg_strdup(item);
3383 /* If nothing matches, free the db structure and return null */
3391 * This function returns in order one of a fixed, NULL pointer terminated list
3392 * of strings (if matching). This can be used if there are only a fixed number
3393 * SQL words that can appear at certain spot.
3396 complete_from_list(const char *text, int state)
3398 static int string_length,
3401 static bool casesensitive;
3404 /* need to have a list */
3405 Assert(completion_charpp != NULL);
3407 /* Initialization */
3411 string_length = strlen(text);
3412 casesensitive = completion_case_sensitive;
3416 while ((item = completion_charpp[list_index++]))
3418 /* First pass is case sensitive */
3419 if (casesensitive && strncmp(text, item, string_length) == 0)
3422 return pg_strdup(item);
3425 /* Second pass is case insensitive, don't bother counting matches */
3426 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
3428 if (completion_case_sensitive)
3429 return pg_strdup(item);
3433 * If case insensitive matching was requested initially,
3434 * adjust the case according to setting.
3436 return pg_strdup_keyword_case(item, text);
3441 * No matches found. If we're not case insensitive already, lets switch to
3442 * being case insensitive and try again
3444 if (casesensitive && matches == 0)
3446 casesensitive = false;
3449 return complete_from_list(text, state);
3452 /* If no more matches, return null. */
3458 * This function returns one fixed string the first time even if it doesn't
3459 * match what's there, and nothing the second time. This should be used if
3460 * there is only one possibility that can appear at a certain spot, so
3461 * misspellings will be overwritten. The string to be passed must be in
3465 complete_from_const(const char *text, int state)
3467 Assert(completion_charp != NULL);
3470 if (completion_case_sensitive)
3471 return pg_strdup(completion_charp);
3475 * If case insensitive matching was requested initially, adjust
3476 * the case according to setting.
3478 return pg_strdup_keyword_case(completion_charp, text);
3486 * This function appends the variable name with prefix and suffix to
3487 * the variable names array.
3490 append_variable_names(char ***varnames, int *nvars,
3491 int *maxvars, const char *varname,
3492 const char *prefix, const char *suffix)
3494 if (*nvars >= *maxvars)
3497 *varnames = (char **) pg_realloc(*varnames,
3498 ((*maxvars) + 1) * sizeof(char *));
3501 (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix);
3506 * This function supports completion with the name of a psql variable.
3507 * The variable names can be prefixed and suffixed with additional text
3508 * to support quoting usages. If need_value is true, only the variables
3509 * that have the set values are picked up.
3512 complete_from_variables(const char *text, const char *prefix, const char *suffix,
3520 struct _variable *ptr;
3522 static const char *const known_varnames[] = {
3523 "AUTOCOMMIT", "COMP_KEYWORD_CASE", "DBNAME", "ECHO", "ECHO_HIDDEN",
3524 "ENCODING", "FETCH_COUNT", "HISTCONTROL", "HISTFILE", "HISTSIZE",
3525 "HOST", "IGNOREEOF", "LASTOID", "ON_ERROR_ROLLBACK", "ON_ERROR_STOP",
3526 "PORT", "PROMPT1", "PROMPT2", "PROMPT3", "QUIET",
3527 "SHOW_CONTEXT", "SINGLELINE", "SINGLESTEP",
3528 "USER", "VERBOSITY", NULL
3531 varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *));
3535 for (i = 0; known_varnames[i] && nvars < maxvars; i++)
3536 append_variable_names(&varnames, &nvars, &maxvars,
3537 known_varnames[i], prefix, suffix);
3540 for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3542 if (need_value && !(ptr->value))
3544 for (i = 0; known_varnames[i]; i++) /* remove duplicate entry */
3546 if (strcmp(ptr->name, known_varnames[i]) == 0)
3549 append_variable_names(&varnames, &nvars, &maxvars, ptr->name,
3553 varnames[nvars] = NULL;
3554 COMPLETE_WITH_LIST_CS((const char *const *) varnames);
3556 for (i = 0; i < nvars; i++)
3565 * This function wraps rl_filename_completion_function() to strip quotes from
3566 * the input before searching for matches and to quote any matches for which
3567 * the consuming command will require it.
3570 complete_from_files(const char *text, int state)
3572 static const char *unquoted_text;
3573 char *unquoted_match;
3578 /* Initialization: stash the unquoted input. */
3579 unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
3580 false, true, pset.encoding);
3581 /* expect a NULL return for the empty string only */
3584 Assert(*text == '\0');
3585 unquoted_text = text;
3589 unquoted_match = filename_completion_function(unquoted_text, state);
3593 * Caller sets completion_charp to a zero- or one-character string
3594 * containing the escape character. This is necessary since \copy has
3595 * no escape character, but every other backslash command recognizes
3596 * "\" as an escape character. Since we have only two callers, don't
3597 * bother providing a macro to simplify this.
3599 ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
3600 '\'', *completion_charp, pset.encoding);
3602 free(unquoted_match);
3604 ret = unquoted_match;
3611 /* HELPER FUNCTIONS */
3615 * Make a pg_strdup copy of s and convert the case according to
3616 * COMP_KEYWORD_CASE setting, using ref as the text that was already entered.
3619 pg_strdup_keyword_case(const char *s, const char *ref)
3623 unsigned char first = ref[0];
3627 if (pset.comp_case == PSQL_COMP_CASE_LOWER ||
3628 ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER ||
3629 pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) ||
3630 (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first)))
3632 for (p = ret; *p; p++)
3633 *p = pg_tolower((unsigned char) *p);
3637 for (p = ret; *p; p++)
3638 *p = pg_toupper((unsigned char) *p);
3646 * escape_string - Escape argument for use as string literal.
3648 * The returned value has to be freed.
3651 escape_string(const char *text)
3656 text_length = strlen(text);
3658 result = pg_malloc(text_length * 2 + 1);
3659 PQescapeStringConn(pset.db, result, text, text_length, NULL);
3666 * Execute a query and report any errors. This should be the preferred way of
3667 * talking to the database in this file.
3670 exec_query(const char *query)
3674 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
3677 result = PQexec(pset.db, query);
3679 if (PQresultStatus(result) != PGRES_TUPLES_OK)
3682 psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
3683 PQerrorMessage(pset.db), query);
3694 * Parse all the word(s) before point.
3696 * Returns a malloc'd array of character pointers that point into the malloc'd
3697 * data array returned to *buffer; caller must free() both of these when done.
3698 * *nwords receives the number of words found, ie, the valid length of the
3701 * Words are returned right to left, that is, previous_words[0] gets the last
3702 * word before point, previous_words[1] the next-to-last, etc.
3705 get_previous_words(int point, char **buffer, int *nwords)
3707 char **previous_words;
3710 int words_found = 0;
3714 * If we have anything in tab_completion_query_buf, paste it together with
3715 * rl_line_buffer to construct the full query. Otherwise we can just use
3716 * rl_line_buffer as the input string.
3718 if (tab_completion_query_buf && tab_completion_query_buf->len > 0)
3720 i = tab_completion_query_buf->len;
3721 buf = pg_malloc(point + i + 2);
3722 memcpy(buf, tab_completion_query_buf->data, i);
3724 memcpy(buf + i, rl_line_buffer, point);
3727 /* Readjust point to reference appropriate offset in buf */
3731 buf = rl_line_buffer;
3734 * Allocate an array of string pointers and a buffer to hold the strings
3735 * themselves. The worst case is that the line contains only
3736 * non-whitespace WORD_BREAKS characters, making each one a separate word.
3737 * This is usually much more space than we need, but it's cheaper than
3738 * doing a separate malloc() for each word.
3740 previous_words = (char **) pg_malloc(point * sizeof(char *));
3741 *buffer = outptr = (char *) pg_malloc(point * 2);
3744 * First we look for a non-word char before the current point. (This is
3745 * probably useless, if readline is on the same page as we are about what
3746 * is a word, but if so it's cheap.)
3748 for (i = point - 1; i >= 0; i--)
3750 if (strchr(WORD_BREAKS, buf[i]))
3756 * Now parse words, working backwards, until we hit start of line. The
3757 * backwards scan has some interesting but intentional properties
3758 * concerning parenthesis handling.
3764 bool inquotes = false;
3765 int parentheses = 0;
3767 /* now find the first non-space which then constitutes the end */
3769 for (i = point; i >= 0; i--)
3771 if (!isspace((unsigned char) buf[i]))
3777 /* if no end found, we're done */
3782 * Otherwise we now look for the start. The start is either the last
3783 * character before any word-break character going backwards from the
3784 * end, or it's simply character 0. We also handle open quotes and
3787 for (start = end; start > 0; start--)
3789 if (buf[start] == '"')
3790 inquotes = !inquotes;
3793 if (buf[start] == ')')
3795 else if (buf[start] == '(')
3797 if (--parentheses <= 0)
3800 else if (parentheses == 0 &&
3801 strchr(WORD_BREAKS, buf[start - 1]))
3806 /* Return the word located at start to end inclusive */
3807 previous_words[words_found++] = outptr;
3808 i = end - start + 1;
3809 memcpy(outptr, &buf[start], i);
3813 /* Continue searching */
3817 /* Release parsing input workspace, if we made one above */
3818 if (buf != rl_line_buffer)
3821 *nwords = words_found;
3822 return previous_words;
3826 * Look up the type for the GUC variable with the passed name.
3828 * Returns NULL if the variable is unknown. Otherwise the returned string,
3829 * containing the type, has to be freed.
3832 get_guctype(const char *varname)
3834 PQExpBufferData query_buffer;
3837 char *guctype = NULL;
3839 e_varname = escape_string(varname);
3841 initPQExpBuffer(&query_buffer);
3842 appendPQExpBuffer(&query_buffer,
3843 "SELECT vartype FROM pg_catalog.pg_settings "
3844 "WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
3847 result = exec_query(query_buffer.data);
3848 termPQExpBuffer(&query_buffer);
3851 if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
3852 guctype = pg_strdup(PQgetvalue(result, 0, 0));
3862 * Surround a string with single quotes. This works for both SQL and
3863 * psql internal. Currently disabled because it is reported not to
3864 * cooperate with certain versions of readline.
3867 quote_file_name(char *text, int match_type, char *quote_pointer)
3872 (void) quote_pointer; /* not used */
3874 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
3875 s = pg_malloc(length);
3877 strcpy(s + 1, text);
3878 if (match_type == SINGLE_MATCH)
3879 s[length - 2] = '\'';
3880 s[length - 1] = '\0';
3885 dequote_file_name(char *text, char quote_char)
3891 return pg_strdup(text);
3893 length = strlen(text);
3894 s = pg_malloc(length - 2 + 1);
3895 strlcpy(s, text +1, length - 2 + 1);
3899 #endif /* NOT_USED */
3901 #endif /* USE_READLINE */