2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2003, PostgreSQL Global Development Group
6 * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.107 2004/05/26 13:56:55 momjian Exp $
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. Also,
32 * - If you split your queries across lines, this whole thing gets
33 * confused. (To fix this, one would have to read psql's query
34 * buffer rather than readline's line buffer, which would require
35 * some major revisions of things.)
37 * - Table or attribute names with spaces in it may confuse it.
39 * - Quotes, parenthesis, and other funny characters are not handled
40 * all that gracefully.
41 *----------------------------------------------------------------------
44 #include "postgres_fe.h"
45 #include "tab-complete.h"
48 /* If we don't have this, we might as well forget about the whole thing: */
53 #include "pqexpbuffer.h"
58 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
59 #define filename_completion_function rl_filename_completion_function
61 /* missing in some header files */
62 extern char *filename_completion_function();
65 #ifdef HAVE_RL_COMPLETION_MATCHES
66 #define completion_matches rl_completion_matches
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.
85 * Selection condition --- only rows meeting this condition are candidates
86 * to display. If catname mentions multiple tables, include the
87 * necessary join condition here. For example, "c.relkind = 'r'".
88 * Write NULL (not an empty string) if not needed.
90 const char *selcondition;
92 * Visibility condition --- which rows are visible without schema
93 * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)".
95 const char *viscondition;
97 * Namespace --- name of field to join to pg_namespace.oid.
98 * For example, "c.relnamespace".
100 const char *namespace;
102 * Result --- the appropriately-quoted name to return, in the case of
103 * an unqualified name. For example, "pg_catalog.quote_ident(c.relname)".
107 * In some cases a different result must be used for qualified names.
108 * Enter that here, or write NULL if result can be used.
110 const char *qualresult;
114 /* Store maximum number of records we want from database queries
115 * (implemented via SELECT ... LIMIT xx).
117 static int completion_max_records;
120 * Communication variables set by COMPLETE_WITH_FOO macros and then used by
121 * the completion callback functions. Ugly but there is no better way.
123 static const char *completion_charp; /* to pass a string */
124 static const char * const *completion_charpp; /* to pass a list of strings */
125 static const char *completion_info_charp; /* to pass a second string */
126 static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
128 /* A couple of macros to ease typing. You can use these to complete the given
130 1) The results from a query you pass it. (Perhaps one of those below?)
131 2) The results from a schema query you pass it.
132 3) The items from a null-pointer-terminated list.
134 5) The list of attributes to the given table.
136 #define COMPLETE_WITH_QUERY(query) \
137 do { completion_charp = query; matches = completion_matches(text, complete_from_query); } while(0)
138 #define COMPLETE_WITH_SCHEMA_QUERY(query,addon) \
139 do { completion_squery = &(query); completion_charp = addon; matches = completion_matches(text, complete_from_schema_query); } while(0)
140 #define COMPLETE_WITH_LIST(list) \
141 do { completion_charpp = list; matches = completion_matches(text, complete_from_list); } while(0)
142 #define COMPLETE_WITH_CONST(string) \
143 do { completion_charp = string; matches = completion_matches(text, complete_from_const); } while(0)
144 #define COMPLETE_WITH_ATTR(table) \
145 do {completion_charp = Query_for_list_of_attributes; completion_info_charp = table; matches = completion_matches(text, complete_from_query); } while(0)
148 * Assembly instructions for schema queries
151 static const SchemaQuery Query_for_list_of_aggregates = {
153 "pg_catalog.pg_proc p",
157 "pg_catalog.pg_function_is_visible(p.oid)",
161 "pg_catalog.quote_ident(p.proname)",
166 static const SchemaQuery Query_for_list_of_datatypes = {
168 "pg_catalog.pg_type t",
169 /* selcondition --- ignore table rowtypes and array types */
171 " OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) "
172 "AND t.typname !~ '^_'",
174 "pg_catalog.pg_type_is_visible(t.oid)",
178 "pg_catalog.format_type(t.oid, NULL)",
180 "pg_catalog.quote_ident(t.typname)"
183 static const SchemaQuery Query_for_list_of_domains = {
185 "pg_catalog.pg_type t",
189 "pg_catalog.pg_type_is_visible(t.oid)",
193 "pg_catalog.quote_ident(t.typname)",
198 static const SchemaQuery Query_for_list_of_functions = {
200 "pg_catalog.pg_proc p",
204 "pg_catalog.pg_function_is_visible(p.oid)",
208 "pg_catalog.quote_ident(p.proname)",
213 static const SchemaQuery Query_for_list_of_indexes = {
215 "pg_catalog.pg_class c",
217 "c.relkind IN ('i')",
219 "pg_catalog.pg_table_is_visible(c.oid)",
223 "pg_catalog.quote_ident(c.relname)",
228 static const SchemaQuery Query_for_list_of_sequences = {
230 "pg_catalog.pg_class c",
232 "c.relkind IN ('S')",
234 "pg_catalog.pg_table_is_visible(c.oid)",
238 "pg_catalog.quote_ident(c.relname)",
243 static const SchemaQuery Query_for_list_of_tables = {
245 "pg_catalog.pg_class c",
247 "c.relkind IN ('r')",
249 "pg_catalog.pg_table_is_visible(c.oid)",
253 "pg_catalog.quote_ident(c.relname)",
258 static const SchemaQuery Query_for_list_of_tisv = {
260 "pg_catalog.pg_class c",
262 "c.relkind IN ('r', 'i', 'S', 'v')",
264 "pg_catalog.pg_table_is_visible(c.oid)",
268 "pg_catalog.quote_ident(c.relname)",
273 static const SchemaQuery Query_for_list_of_tsv = {
275 "pg_catalog.pg_class c",
277 "c.relkind IN ('r', 'S', 'v')",
279 "pg_catalog.pg_table_is_visible(c.oid)",
283 "pg_catalog.quote_ident(c.relname)",
288 static const SchemaQuery Query_for_list_of_views = {
290 "pg_catalog.pg_class c",
292 "c.relkind IN ('v')",
294 "pg_catalog.pg_table_is_visible(c.oid)",
298 "pg_catalog.quote_ident(c.relname)",
305 * Queries to get lists of names of various kinds of things, possibly
306 * restricted to names matching a partially entered name. In these queries,
307 * %s will be replaced by the text entered so far (suitably escaped to
308 * become a SQL literal string). %d will be replaced by the length of the
309 * string (in unescaped form). A second %s, if present, will be replaced
310 * by a suitably-escaped version of the string provided in
311 * completion_info_charp.
313 * Beware that the allowed sequences of %s and %d are determined by
314 * _complete_from_query().
317 #define Query_for_list_of_attributes \
318 "SELECT pg_catalog.quote_ident(attname) "\
319 " FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\
320 " WHERE c.oid = a.attrelid "\
321 " AND a.attnum > 0 "\
322 " AND NOT a.attisdropped "\
323 " AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\
324 " AND pg_catalog.quote_ident(relname)='%s' "\
325 " AND pg_catalog.pg_table_is_visible(c.oid)"
327 #define Query_for_list_of_databases \
328 "SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\
329 " WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'"
331 #define Query_for_list_of_encodings \
332 " SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\
333 " FROM pg_catalog.pg_conversion "\
334 " WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')"
336 #define Query_for_list_of_languages \
337 "SELECT pg_catalog.quote_ident(lanname) "\
338 " FROM pg_language "\
339 " WHERE lanname != 'internal' "\
340 " AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s' "
342 #define Query_for_list_of_schemas \
343 "SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\
344 " WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
346 #define Query_for_list_of_system_relations \
347 "SELECT pg_catalog.quote_ident(relname) "\
348 " FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "\
349 " WHERE c.relkind IN ('r', 'v', 's', 'S') "\
350 " AND substring(pg_catalog.quote_ident(relname),1,%d)='%s' "\
351 " AND c.relnamespace = n.oid "\
352 " AND n.nspname = 'pg_catalog'"
354 #define Query_for_list_of_users \
355 " SELECT pg_catalog.quote_ident(usename) "\
356 " FROM pg_catalog.pg_user "\
357 " WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
359 /* the silly-looking length condition is just to eat up the current word */
360 #define Query_for_table_owning_index \
361 "SELECT pg_catalog.quote_ident(c1.relname) "\
362 " FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\
363 " WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\
364 " and (%d = length('%s'))"\
365 " and pg_catalog.quote_ident(c2.relname)='%s'"\
366 " and pg_catalog.pg_table_is_visible(c2.oid)"
369 * This is a list of all "things" in Pgsql, which can show up after CREATE or
370 * DROP; and there is also a query to get a list of them.
376 const char *query; /* simple query, or NULL */
377 const SchemaQuery *squery; /* schema query, or NULL */
380 static const pgsql_thing_t words_after_create[] = {
381 {"AGGREGATE", NULL, &Query_for_list_of_aggregates},
382 {"CAST", NULL, NULL}, /* Casts have complex structures for
383 * names, so skip it */
384 {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
385 {"DATABASE", Query_for_list_of_databases},
386 {"DOMAIN", NULL, &Query_for_list_of_domains},
387 {"FUNCTION", NULL, &Query_for_list_of_functions},
388 {"GROUP", "SELECT pg_catalog.quote_ident(groname) FROM pg_catalog.pg_group WHERE substring(pg_catalog.quote_ident(groname),1,%d)='%s'"},
389 {"LANGUAGE", Query_for_list_of_languages},
390 {"INDEX", NULL, &Query_for_list_of_indexes},
391 {"OPERATOR", NULL, NULL}, /* Querying for this is probably
392 * not such a good idea. */
393 {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
394 {"SCHEMA", Query_for_list_of_schemas},
395 {"SEQUENCE", NULL, &Query_for_list_of_sequences},
396 {"TABLE", NULL, &Query_for_list_of_tables},
397 {"TEMP", NULL, NULL}, /* for CREATE TEMP TABLE ... */
398 {"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s'"},
399 {"TYPE", NULL, &Query_for_list_of_datatypes},
400 {"UNIQUE", NULL, NULL}, /* for CREATE UNIQUE INDEX ... */
401 {"USER", Query_for_list_of_users},
402 {"VIEW", NULL, &Query_for_list_of_views},
403 {NULL, NULL, NULL} /* end of list */
407 /* Forward declaration of functions */
408 static char **psql_completion(char *text, int start, int end);
409 static char *create_command_generator(const char *text, int state);
410 static char *complete_from_query(const char *text, int state);
411 static char *complete_from_schema_query(const char *text, int state);
412 static char *_complete_from_query(int is_schema_query,
413 const char *text, int state);
414 static char *complete_from_const(const char *text, int state);
415 static char *complete_from_list(const char *text, int state);
417 static PGresult *exec_query(const char *query);
419 static char *previous_word(int point, int skip);
422 static char *quote_file_name(char *text, int match_type, char *quote_pointer);
423 static char *dequote_file_name(char *text, char quote_char);
427 /* Initialize the readline library for our purposes. */
429 initialize_readline(void)
431 rl_readline_name = (char *)pset.progname;
432 rl_attempted_completion_function = (void *) psql_completion;
434 rl_basic_word_break_characters = "\t\n@$><=;|&{( ";
436 completion_max_records = 1000;
439 * There is a variable rl_completion_query_items for this but
440 * apparently it's not defined everywhere.
445 /* The completion function. Acc. to readline spec this gets passed the text
446 entered to far and its start and end in the readline buffer. The return value
447 is some partially obscure list format that can be generated by the readline
448 libraries completion_matches() function, so we don't have to worry about it.
451 psql_completion(char *text, int start, int end)
453 /* This is the variable we'll return. */
454 char **matches = NULL;
456 /* These are going to contain some scannage of the input line. */
462 static const char * const sql_commands[] = {
463 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT",
464 "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", "DELETE", "DROP", "EXECUTE",
465 "EXPLAIN", "FETCH", "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY",
466 "PREPARE", "REINDEX", "RESET", "REVOKE", "ROLLBACK", "SELECT", "SET", "SHOW", "START",
467 "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", NULL
470 static const char * const pgsql_variables[] = {
471 /* these SET arguments are known in gram.y */
478 * the rest should match USERSET and possibly SUSET entries in
479 * backend/utils/misc/guc.c.
482 "australian_timezones",
484 "client_min_messages",
487 "cpu_index_tuple_cost",
492 "debug_pretty_print",
495 "debug_print_rewritten",
496 "default_statistics_target",
497 "default_transaction_isolation",
498 "default_transaction_read_only",
500 "dynamic_library_path",
501 "effective_cache_size",
510 "explain_pretty_print",
511 "extra_float_digits",
512 "from_collapse_limit",
518 "geqo_selection_bias",
520 "join_collapse_limit",
521 "krb_server_keyfile",
528 "log_error_verbosity",
529 "log_executor_stats",
530 "log_min_duration_statement",
531 "log_min_error_statement",
536 "log_statement_stats",
537 "maintenance_work_mem",
539 "max_files_per_process",
542 "max_locks_per_transaction",
544 "password_encryption",
556 "stats_command_string",
557 "stats_reset_on_server_start",
559 "stats_start_collector",
560 "superuser_reserved_connections",
565 "transform_null_equals",
566 "unix_socket_directory",
568 "unix_socket_permissions",
576 static const char * const backslash_commands[] = {
577 "\\a", "\\connect", "\\C", "\\cd", "\\copy", "\\copyright",
578 "\\d", "\\da", "\\dc", "\\dC", "\\dd", "\\dD", "\\df", "\\dg", "\\di",
579 "\\dl", "\\dn", "\\do", "\\dp", "\\ds", "\\dS", "\\dt", "\\dT",
581 "\\e", "\\echo", "\\encoding",
582 "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
583 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
584 "\\o", "\\p", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\t", "\\T",
585 "\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
588 (void) end; /* not used */
590 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
591 rl_completion_append_character = ' ';
594 /* Clear a few things. */
595 completion_charp = NULL;
596 completion_charpp = NULL;
597 completion_info_charp = NULL;
600 * Scan the input line before our current position for the last four
601 * words. According to those we'll make some smart decisions on what
602 * the user is probably intending to type. TODO: Use strtokx() to do
605 prev_wd = previous_word(start, 0);
606 prev2_wd = previous_word(start, 1);
607 prev3_wd = previous_word(start, 2);
608 prev4_wd = previous_word(start, 3);
610 /* If a backslash command was started, continue */
612 COMPLETE_WITH_LIST(backslash_commands);
614 /* If no previous word, suggest one of the basic sql commands */
616 COMPLETE_WITH_LIST(sql_commands);
618 /* CREATE or DROP but not ALTER TABLE sth DROP */
619 /* complete with something you can create or drop */
620 else if (pg_strcasecmp(prev_wd, "CREATE") == 0 ||
621 (pg_strcasecmp(prev_wd, "DROP") == 0 &&
622 pg_strcasecmp(prev3_wd, "TABLE") != 0))
623 matches = completion_matches(text, create_command_generator);
628 * complete with what you can alter (TABLE, GROUP, USER, ...) unless
629 * we're in ALTER TABLE sth ALTER
631 else if (pg_strcasecmp(prev_wd, "ALTER") == 0 &&
632 pg_strcasecmp(prev3_wd, "TABLE") != 0)
634 static const char *const list_ALTER[] =
635 {"DATABASE", "GROUP", "SCHEMA", "TABLE", "TRIGGER", "USER", NULL};
637 COMPLETE_WITH_LIST(list_ALTER);
640 /* ALTER DATABASE <name> */
641 else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
642 pg_strcasecmp(prev2_wd, "DATABASE") == 0)
644 static const char *const list_ALTERDATABASE[] =
645 {"RESET", "SET", "OWNER TO", "RENAME TO", NULL};
647 COMPLETE_WITH_LIST(list_ALTERDATABASE);
649 /* ALTER TRIGGER <name>, add ON */
650 else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
651 pg_strcasecmp(prev2_wd, "TRIGGER") == 0)
652 COMPLETE_WITH_CONST("ON");
655 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
657 else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
658 pg_strcasecmp(prev3_wd, "TRIGGER") == 0 &&
659 pg_strcasecmp(prev_wd, "ON") == 0)
660 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
663 * If we detect ALTER TABLE <name>, suggest either ADD, DROP, ALTER,
666 else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
667 pg_strcasecmp(prev2_wd, "TABLE") == 0)
669 static const char *const list_ALTER2[] =
670 {"ADD", "ALTER", "DROP", "RENAME", "OWNER TO", NULL};
672 COMPLETE_WITH_LIST(list_ALTER2);
674 /* If we have TABLE <sth> ALTER|RENAME, provide list of columns */
675 else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
676 (pg_strcasecmp(prev_wd, "ALTER") == 0 ||
677 pg_strcasecmp(prev_wd, "RENAME") == 0))
678 COMPLETE_WITH_ATTR(prev2_wd);
680 /* If we have TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
681 else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
682 pg_strcasecmp(prev_wd, "DROP") == 0)
684 static const char *const list_TABLEDROP[] =
685 {"COLUMN", "CONSTRAINT", NULL};
687 COMPLETE_WITH_LIST(list_TABLEDROP);
689 /* If we have TABLE <sth> DROP COLUMN, provide list of columns */
690 else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
691 pg_strcasecmp(prev2_wd, "DROP") == 0 &&
692 pg_strcasecmp(prev_wd, "COLUMN") == 0)
693 COMPLETE_WITH_ATTR(prev3_wd);
695 /* complete ALTER GROUP <foo> with ADD or DROP */
696 else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
697 pg_strcasecmp(prev2_wd, "GROUP") == 0)
699 static const char *const list_ALTERGROUP[] =
700 {"ADD", "DROP", NULL};
702 COMPLETE_WITH_LIST(list_ALTERGROUP);
704 /* complete ALTER GROUP <foo> ADD|DROP with USER */
705 else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
706 pg_strcasecmp(prev3_wd, "GROUP") == 0 &&
707 (pg_strcasecmp(prev_wd, "ADD") == 0 ||
708 pg_strcasecmp(prev_wd, "DROP") == 0))
709 COMPLETE_WITH_CONST("USER");
710 /* complete {ALTER} GROUP <foo> ADD|DROP USER with a user name */
711 else if (pg_strcasecmp(prev4_wd, "GROUP") == 0 &&
712 (pg_strcasecmp(prev2_wd, "ADD") == 0 ||
713 pg_strcasecmp(prev2_wd, "DROP") == 0) &&
714 pg_strcasecmp(prev_wd, "USER") == 0)
715 COMPLETE_WITH_QUERY(Query_for_list_of_users);
718 /* If the previous word is ANALYZE, produce list of tables. */
719 else if (pg_strcasecmp(prev_wd, "ANALYZE") == 0)
720 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
721 /* If we have ANALYZE <table>, complete with semicolon. */
722 else if (pg_strcasecmp(prev2_wd, "ANALYZE") == 0)
723 COMPLETE_WITH_CONST(";");
725 /* BEGIN, COMMIT, ROLLBACK, ABORT, */
726 else if (pg_strcasecmp(prev_wd, "BEGIN") == 0 ||
727 pg_strcasecmp(prev_wd, "END") == 0 ||
728 pg_strcasecmp(prev_wd, "COMMIT") == 0 ||
729 pg_strcasecmp(prev_wd, "ROLLBACK") == 0 ||
730 pg_strcasecmp(prev_wd, "ABORT") == 0)
732 static const char * const list_TRANS[] =
733 {"WORK", "TRANSACTION", NULL};
735 COMPLETE_WITH_LIST(list_TRANS);
738 /* If the previous word is CLUSTER, produce list of indexes. */
739 else if (pg_strcasecmp(prev_wd, "CLUSTER") == 0)
740 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
741 /* If we have CLUSTER <sth>, then add "ON" */
742 else if (pg_strcasecmp(prev2_wd, "CLUSTER") == 0)
743 COMPLETE_WITH_CONST("ON");
746 * If we have CLUSTER <sth> ON, then add the correct tablename as
749 else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 &&
750 pg_strcasecmp(prev_wd, "ON") == 0)
752 completion_info_charp = prev2_wd;
753 COMPLETE_WITH_QUERY(Query_for_table_owning_index);
757 else if (pg_strcasecmp(prev_wd, "COMMENT") == 0)
758 COMPLETE_WITH_CONST("ON");
759 else if (pg_strcasecmp(prev2_wd, "COMMENT") == 0 &&
760 pg_strcasecmp(prev_wd, "ON") == 0)
762 static const char *const list_COMMENT[] =
763 {"DATABASE", "INDEX", "RULE", "SCHEMA", "SEQUENCE", "TABLE",
764 "TYPE", "VIEW", "COLUMN", "AGGREGATE", "FUNCTION", "OPERATOR",
765 "TRIGGER", "CONSTRAINT", "DOMAIN", NULL};
767 COMPLETE_WITH_LIST(list_COMMENT);
769 else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 &&
770 pg_strcasecmp(prev3_wd, "ON") == 0)
771 COMPLETE_WITH_CONST("IS");
776 * If we have COPY [BINARY] (which you'd have to type yourself), offer
777 * list of tables (Also cover the analogous backslash command)
779 else if (pg_strcasecmp(prev_wd, "COPY") == 0 ||
780 pg_strcasecmp(prev_wd, "\\copy") == 0 ||
781 (pg_strcasecmp(prev2_wd, "COPY") == 0 &&
782 pg_strcasecmp(prev_wd, "BINARY") == 0))
783 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
784 /* If we have COPY|BINARY <sth>, complete it with "TO" or "FROM" */
785 else if (pg_strcasecmp(prev2_wd, "COPY") == 0 ||
786 pg_strcasecmp(prev2_wd, "\\copy") == 0 ||
787 pg_strcasecmp(prev2_wd, "BINARY") == 0)
789 static const char *const list_FROMTO[] =
790 {"FROM", "TO", NULL};
792 COMPLETE_WITH_LIST(list_FROMTO);
796 /* First off we complete CREATE UNIQUE with "INDEX" */
797 else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
798 pg_strcasecmp(prev_wd, "UNIQUE") == 0)
799 COMPLETE_WITH_CONST("INDEX");
800 /* If we have CREATE|UNIQUE INDEX <sth>, then add "ON" */
801 else if (pg_strcasecmp(prev2_wd, "INDEX") == 0 &&
802 (pg_strcasecmp(prev3_wd, "CREATE") == 0 ||
803 pg_strcasecmp(prev3_wd, "UNIQUE") == 0))
804 COMPLETE_WITH_CONST("ON");
805 /* Complete ... INDEX <name> ON with a list of tables */
806 else if (pg_strcasecmp(prev3_wd, "INDEX") == 0 &&
807 pg_strcasecmp(prev_wd, "ON") == 0)
808 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
811 * Complete INDEX <name> ON <table> with a list of table columns
812 * (which should really be in parens)
814 else if (pg_strcasecmp(prev4_wd, "INDEX") == 0 &&
815 pg_strcasecmp(prev2_wd, "ON") == 0)
816 COMPLETE_WITH_ATTR(prev_wd);
817 /* same if you put in USING */
818 else if (pg_strcasecmp(prev4_wd, "ON") == 0 &&
819 pg_strcasecmp(prev2_wd, "USING") == 0)
820 COMPLETE_WITH_ATTR(prev3_wd);
821 /* Complete USING with an index method */
822 else if (pg_strcasecmp(prev_wd, "USING") == 0)
824 static const char *const index_mth[] =
825 {"BTREE", "RTREE", "HASH", "GIST", NULL};
827 COMPLETE_WITH_LIST(index_mth);
831 /* Complete "CREATE RULE <sth>" with "AS" */
832 else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
833 pg_strcasecmp(prev2_wd, "RULE") == 0)
834 COMPLETE_WITH_CONST("AS");
835 /* Complete "CREATE RULE <sth> AS with "ON" */
836 else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
837 pg_strcasecmp(prev3_wd, "RULE") == 0 &&
838 pg_strcasecmp(prev_wd, "AS") == 0)
839 COMPLETE_WITH_CONST("ON");
840 /* Complete "RULE * AS ON" with SELECT|UPDATE|DELETE|INSERT */
841 else if (pg_strcasecmp(prev4_wd, "RULE") == 0 &&
842 pg_strcasecmp(prev2_wd, "AS") == 0 &&
843 pg_strcasecmp(prev_wd, "ON") == 0)
845 static const char *const rule_events[] =
846 {"SELECT", "UPDATE", "INSERT", "DELETE", NULL};
848 COMPLETE_WITH_LIST(rule_events);
850 /* Complete "AS ON <sth with a 'T' :)>" with a "TO" */
851 else if (pg_strcasecmp(prev3_wd, "AS") == 0 &&
852 pg_strcasecmp(prev2_wd, "ON") == 0 &&
853 (toupper((unsigned char) prev_wd[4]) == 'T' ||
854 toupper((unsigned char) prev_wd[5]) == 'T'))
855 COMPLETE_WITH_CONST("TO");
856 /* Complete "AS ON <sth> TO" with a table name */
857 else if (pg_strcasecmp(prev4_wd, "AS") == 0 &&
858 pg_strcasecmp(prev3_wd, "ON") == 0 &&
859 pg_strcasecmp(prev_wd, "TO") == 0)
860 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
863 /* Complete CREATE TEMP with "TABLE" */
864 else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
865 pg_strcasecmp(prev_wd, "TEMP") == 0)
866 COMPLETE_WITH_CONST("TABLE");
869 /* is on the agenda . . . */
872 /* Complete "CREATE VIEW <name>" with "AS" */
873 else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
874 pg_strcasecmp(prev2_wd, "VIEW") == 0)
875 COMPLETE_WITH_CONST("AS");
876 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
877 else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
878 pg_strcasecmp(prev3_wd, "VIEW") == 0 &&
879 pg_strcasecmp(prev_wd, "AS") == 0)
880 COMPLETE_WITH_CONST("SELECT");
885 * Complete DELETE with FROM (only if the word before that is not "ON"
886 * (cf. rules) or "BEFORE" or "AFTER" (cf. triggers) or GRANT)
888 else if (pg_strcasecmp(prev_wd, "DELETE") == 0 &&
889 !(pg_strcasecmp(prev2_wd, "ON") == 0 ||
890 pg_strcasecmp(prev2_wd, "GRANT") == 0 ||
891 pg_strcasecmp(prev2_wd, "BEFORE") == 0 ||
892 pg_strcasecmp(prev2_wd, "AFTER") == 0))
893 COMPLETE_WITH_CONST("FROM");
894 /* Complete DELETE FROM with a list of tables */
895 else if (pg_strcasecmp(prev2_wd, "DELETE") == 0 &&
896 pg_strcasecmp(prev_wd, "FROM") == 0)
897 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
898 /* Complete DELETE FROM <table> with "WHERE" (perhaps a safe idea?) */
899 else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 &&
900 pg_strcasecmp(prev2_wd, "FROM") == 0)
901 COMPLETE_WITH_CONST("WHERE");
906 * Complete EXPLAIN [VERBOSE] (which you'd have to type yourself) with
907 * the list of SQL commands
909 else if (pg_strcasecmp(prev_wd, "EXPLAIN") == 0 ||
910 (pg_strcasecmp(prev2_wd, "EXPLAIN") == 0 &&
911 pg_strcasecmp(prev_wd, "VERBOSE") == 0))
912 COMPLETE_WITH_LIST(sql_commands);
915 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
916 else if (pg_strcasecmp(prev_wd, "FETCH") == 0 ||
917 pg_strcasecmp(prev_wd, "MOVE") == 0)
919 static const char * const list_FETCH1[] =
920 {"FORWARD", "BACKWARD", "RELATIVE", NULL};
922 COMPLETE_WITH_LIST(list_FETCH1);
924 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
925 else if (pg_strcasecmp(prev2_wd, "FETCH") == 0 ||
926 pg_strcasecmp(prev2_wd, "MOVE") == 0)
928 static const char * const list_FETCH2[] =
929 {"ALL", "NEXT", "PRIOR", NULL};
931 COMPLETE_WITH_LIST(list_FETCH2);
935 * Complete FETCH <sth1> <sth2> with "FROM" or "TO". (Is there a
936 * difference? If not, remove one.)
938 else if (pg_strcasecmp(prev3_wd, "FETCH") == 0 ||
939 pg_strcasecmp(prev3_wd, "MOVE") == 0)
941 static const char * const list_FROMTO[] =
942 {"FROM", "TO", NULL};
944 COMPLETE_WITH_LIST(list_FROMTO);
948 /* Complete GRANT/REVOKE with a list of privileges */
949 else if (pg_strcasecmp(prev_wd, "GRANT") == 0 ||
950 pg_strcasecmp(prev_wd, "REVOKE") == 0)
952 static const char * const list_privileg[] =
953 {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES",
954 "TRIGGER", "CREATE", "TEMPORARY", "EXECUTE", "USAGE", "ALL", NULL};
956 COMPLETE_WITH_LIST(list_privileg);
958 /* Complete GRANT/REVOKE <sth> with "ON" */
959 else if (pg_strcasecmp(prev2_wd, "GRANT") == 0 ||
960 pg_strcasecmp(prev2_wd, "REVOKE") == 0)
961 COMPLETE_WITH_CONST("ON");
964 * Complete GRANT/REVOKE <sth> ON with a list of tables, views,
965 * sequences, and indexes
967 * keywords DATABASE, FUNCTION, LANGUAGE, SCHEMA added to query result
968 * via UNION; seems to work intuitively
970 * Note: GRANT/REVOKE can get quite complex; tab-completion as
971 * implemented here will only work if the privilege list contains
972 * exactly one privilege
974 else if ((pg_strcasecmp(prev3_wd, "GRANT") == 0 ||
975 pg_strcasecmp(prev3_wd, "REVOKE") == 0) &&
976 pg_strcasecmp(prev_wd, "ON") == 0)
977 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv,
978 " UNION SELECT 'DATABASE'"
979 " UNION SELECT 'FUNCTION'"
980 " UNION SELECT 'LANGUAGE'"
981 " UNION SELECT 'SCHEMA'");
983 /* Complete "GRANT/REVOKE * ON * " with "TO" */
984 else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 ||
985 pg_strcasecmp(prev4_wd, "REVOKE") == 0) &&
986 pg_strcasecmp(prev2_wd, "ON") == 0)
988 if (pg_strcasecmp(prev_wd, "DATABASE") == 0)
989 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
990 else if (pg_strcasecmp(prev_wd, "FUNCTION") == 0)
991 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
992 else if (pg_strcasecmp(prev_wd, "LANGUAGE") == 0)
993 COMPLETE_WITH_QUERY(Query_for_list_of_languages);
994 else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0)
995 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
997 COMPLETE_WITH_CONST("TO");
1001 * TODO: to complete with user name we need prev5_wd -- wait for a
1002 * more general solution there same for GRANT <sth> ON { DATABASE |
1003 * FUNCTION | LANGUAGE | SCHEMA } xxx TO
1007 /* Complete INSERT with "INTO" */
1008 else if (pg_strcasecmp(prev_wd, "INSERT") == 0)
1009 COMPLETE_WITH_CONST("INTO");
1010 /* Complete INSERT INTO with table names */
1011 else if (pg_strcasecmp(prev2_wd, "INSERT") == 0 &&
1012 pg_strcasecmp(prev_wd, "INTO") == 0)
1013 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1014 /* Complete "INSERT INTO <table> (" with attribute names */
1015 else if (rl_line_buffer[start - 1] == '(' &&
1016 pg_strcasecmp(prev3_wd, "INSERT") == 0 &&
1017 pg_strcasecmp(prev2_wd, "INTO") == 0)
1018 COMPLETE_WITH_ATTR(prev_wd);
1021 * Complete INSERT INTO <table> with "VALUES" or "SELECT" or "DEFAULT
1024 else if (pg_strcasecmp(prev3_wd, "INSERT") == 0 &&
1025 pg_strcasecmp(prev2_wd, "INTO") == 0)
1027 static const char * const list_INSERT[] =
1028 {"DEFAULT VALUES", "SELECT", "VALUES", NULL};
1030 COMPLETE_WITH_LIST(list_INSERT);
1032 /* Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" */
1033 else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 &&
1034 pg_strcasecmp(prev3_wd, "INTO") == 0 &&
1035 prev_wd[strlen(prev_wd) - 1] == ')')
1037 static const char * const list_INSERT[] =
1038 {"SELECT", "VALUES", NULL};
1040 COMPLETE_WITH_LIST(list_INSERT);
1043 /* Insert an open parenthesis after "VALUES" */
1044 else if (pg_strcasecmp(prev_wd, "VALUES") == 0 &&
1045 pg_strcasecmp(prev2_wd, "DEFAULT") != 0)
1046 COMPLETE_WITH_CONST("(");
1049 /* Complete LOCK [TABLE] with a list of tables */
1050 else if (pg_strcasecmp(prev_wd, "LOCK") == 0 ||
1051 (pg_strcasecmp(prev_wd, "TABLE") == 0 &&
1052 pg_strcasecmp(prev2_wd, "LOCK") == 0))
1053 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1055 /* For the following, handle the case of a single table only for now */
1057 /* Complete LOCK [TABLE] <table> with "IN" */
1058 else if ((pg_strcasecmp(prev2_wd, "LOCK") == 0 &&
1059 pg_strcasecmp(prev_wd, "TABLE")) ||
1060 (pg_strcasecmp(prev2_wd, "TABLE") == 0 &&
1061 pg_strcasecmp(prev3_wd, "LOCK") == 0))
1062 COMPLETE_WITH_CONST("IN");
1064 /* Complete LOCK [TABLE] <table> IN with a lock mode */
1065 else if (pg_strcasecmp(prev_wd, "IN") == 0 &&
1066 (pg_strcasecmp(prev3_wd, "LOCK") == 0 ||
1067 (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
1068 pg_strcasecmp(prev4_wd, "LOCK") == 0)))
1070 static const char * const lock_modes[] =
1071 {"ACCESS SHARE MODE",
1072 "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
1073 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE",
1074 "SHARE ROW EXCLUSIVE MODE",
1075 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE", NULL};
1077 COMPLETE_WITH_LIST(lock_modes);
1081 else if (pg_strcasecmp(prev_wd, "NOTIFY") == 0)
1082 COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(relname) FROM pg_catalog.pg_listener WHERE substring(pg_catalog.quote_ident(relname),1,%d)='%s'");
1085 else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
1087 static const char * const list_REINDEX[] =
1088 {"TABLE", "DATABASE", "INDEX", NULL};
1090 COMPLETE_WITH_LIST(list_REINDEX);
1092 else if (pg_strcasecmp(prev2_wd, "REINDEX") == 0)
1094 if (pg_strcasecmp(prev_wd, "TABLE") == 0)
1095 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1096 else if (pg_strcasecmp(prev_wd, "DATABASE") == 0)
1097 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
1098 else if (pg_strcasecmp(prev_wd, "INDEX") == 0)
1099 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
1105 /* SET, RESET, SHOW */
1106 /* Complete with a variable name */
1107 else if ((pg_strcasecmp(prev_wd, "SET") == 0 &&
1108 pg_strcasecmp(prev3_wd, "UPDATE") != 0) ||
1109 pg_strcasecmp(prev_wd, "RESET") == 0 ||
1110 pg_strcasecmp(prev_wd, "SHOW") == 0)
1111 COMPLETE_WITH_LIST(pgsql_variables);
1112 /* Complete "SET TRANSACTION" */
1113 else if ((pg_strcasecmp(prev2_wd, "SET") == 0 &&
1114 pg_strcasecmp(prev_wd, "TRANSACTION") == 0)
1115 || (pg_strcasecmp(prev2_wd, "START") == 0
1116 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0)
1117 || (pg_strcasecmp(prev2_wd, "BEGIN") == 0
1118 && pg_strcasecmp(prev_wd, "WORK") == 0)
1119 || (pg_strcasecmp(prev2_wd, "BEGIN") == 0
1120 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0)
1121 || (pg_strcasecmp(prev4_wd, "SESSION") == 0
1122 && pg_strcasecmp(prev3_wd, "CHARACTERISTICS") == 0
1123 && pg_strcasecmp(prev2_wd, "AS") == 0
1124 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0))
1126 static const char * const my_list[] =
1127 {"ISOLATION", "READ", NULL};
1129 COMPLETE_WITH_LIST(my_list);
1131 else if ((pg_strcasecmp(prev3_wd, "SET") == 0
1132 || pg_strcasecmp(prev3_wd, "START") == 0
1133 || (pg_strcasecmp(prev4_wd, "CHARACTERISTICS") == 0
1134 && pg_strcasecmp(prev3_wd, "AS") == 0))
1135 && pg_strcasecmp(prev2_wd, "TRANSACTION") == 0
1136 && pg_strcasecmp(prev_wd, "ISOLATION") == 0)
1137 COMPLETE_WITH_CONST("LEVEL");
1138 else if ((pg_strcasecmp(prev4_wd, "SET") == 0
1139 || pg_strcasecmp(prev4_wd, "START") == 0
1140 || pg_strcasecmp(prev4_wd, "AS") == 0)
1141 && pg_strcasecmp(prev3_wd, "TRANSACTION") == 0
1142 && pg_strcasecmp(prev2_wd, "ISOLATION") == 0
1143 && pg_strcasecmp(prev_wd, "LEVEL") == 0)
1145 static const char * const my_list[] =
1146 {"READ", "REPEATABLE", "SERIALIZABLE", NULL};
1148 COMPLETE_WITH_LIST(my_list);
1150 else if (pg_strcasecmp(prev4_wd, "TRANSACTION") == 0 &&
1151 pg_strcasecmp(prev3_wd, "ISOLATION") == 0 &&
1152 pg_strcasecmp(prev2_wd, "LEVEL") == 0 &&
1153 pg_strcasecmp(prev_wd, "READ") == 0)
1155 static const char * const my_list[] =
1156 {"UNCOMMITTED", "COMMITTED", NULL};
1158 COMPLETE_WITH_LIST(my_list);
1160 else if (pg_strcasecmp(prev4_wd, "TRANSACTION") == 0 &&
1161 pg_strcasecmp(prev3_wd, "ISOLATION") == 0 &&
1162 pg_strcasecmp(prev2_wd, "LEVEL") == 0 &&
1163 pg_strcasecmp(prev_wd, "REPEATABLE") == 0)
1164 COMPLETE_WITH_CONST("READ");
1165 else if ((pg_strcasecmp(prev3_wd, "SET") == 0 ||
1166 pg_strcasecmp(prev3_wd, "AS") == 0) &&
1167 pg_strcasecmp(prev2_wd, "TRANSACTION") == 0 &&
1168 pg_strcasecmp(prev_wd, "READ") == 0)
1170 static const char * const my_list[] =
1171 {"ONLY", "WRITE", NULL};
1173 COMPLETE_WITH_LIST(my_list);
1175 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
1176 else if (pg_strcasecmp(prev3_wd, "SET") == 0 &&
1177 pg_strcasecmp(prev2_wd, "CONSTRAINTS") == 0)
1179 static const char * const constraint_list[] =
1180 {"DEFERRED", "IMMEDIATE", NULL};
1182 COMPLETE_WITH_LIST(constraint_list);
1184 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
1185 else if (pg_strcasecmp(prev2_wd, "SET") == 0 &&
1186 pg_strcasecmp(prev_wd, "SESSION") == 0)
1188 static const char * const my_list[] =
1189 {"AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION", NULL};
1191 COMPLETE_WITH_LIST(my_list);
1193 /* Complete SET SESSION AUTHORIZATION with username */
1194 else if (pg_strcasecmp(prev3_wd, "SET") == 0
1195 && pg_strcasecmp(prev2_wd, "SESSION") == 0
1196 && pg_strcasecmp(prev_wd, "AUTHORIZATION") == 0)
1197 COMPLETE_WITH_QUERY(Query_for_list_of_users);
1198 /* Complete SET <var> with "TO" */
1199 else if (pg_strcasecmp(prev2_wd, "SET") == 0 &&
1200 pg_strcasecmp(prev4_wd, "UPDATE") != 0)
1201 COMPLETE_WITH_CONST("TO");
1202 /* Suggest possible variable values */
1203 else if (pg_strcasecmp(prev3_wd, "SET") == 0 &&
1204 (pg_strcasecmp(prev_wd, "TO") == 0 || strcmp(prev_wd, "=") == 0))
1206 if (pg_strcasecmp(prev2_wd, "DateStyle") == 0)
1208 static const char * const my_list[] =
1209 {"ISO", "SQL", "Postgres", "German",
1210 "YMD", "DMY", "MDY",
1211 "US", "European", "NonEuropean",
1214 COMPLETE_WITH_LIST(my_list);
1216 else if (pg_strcasecmp(prev2_wd, "GEQO") == 0)
1218 static const char * const my_list[] =
1219 {"ON", "OFF", "DEFAULT", NULL};
1221 COMPLETE_WITH_LIST(my_list);
1225 static const char * const my_list[] =
1228 COMPLETE_WITH_LIST(my_list);
1232 /* START TRANSACTION */
1233 else if (pg_strcasecmp(prev_wd, "START") == 0)
1234 COMPLETE_WITH_CONST("TRANSACTION");
1237 else if (pg_strcasecmp(prev_wd, "TRUNCATE") == 0)
1238 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1241 else if (pg_strcasecmp(prev_wd, "UNLISTEN") == 0)
1242 COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(relname) FROM pg_catalog.pg_listener WHERE substring(pg_catalog.quote_ident(relname),1,%d)='%s' UNION SELECT '*'");
1245 /* If prev. word is UPDATE suggest a list of tables */
1246 else if (pg_strcasecmp(prev_wd, "UPDATE") == 0)
1247 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1248 /* Complete UPDATE <table> with "SET" */
1249 else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0)
1250 COMPLETE_WITH_CONST("SET");
1253 * If the previous word is SET (and it wasn't caught above as the
1254 * _first_ word) the word before it was (hopefully) a table name and
1255 * we'll now make a list of attributes.
1257 else if (pg_strcasecmp(prev_wd, "SET") == 0)
1258 COMPLETE_WITH_ATTR(prev2_wd);
1261 else if (pg_strcasecmp(prev_wd, "VACUUM") == 0)
1262 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
1263 " UNION SELECT 'FULL'"
1264 " UNION SELECT 'ANALYZE'"
1265 " UNION SELECT 'VERBOSE'");
1266 else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 &&
1267 (pg_strcasecmp(prev_wd, "FULL") == 0 ||
1268 pg_strcasecmp(prev_wd, "ANALYZE") == 0 ||
1269 pg_strcasecmp(prev_wd, "VERBOSE") == 0))
1270 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1273 /* Simple case of the word before the where being the table name */
1274 else if (pg_strcasecmp(prev_wd, "WHERE") == 0)
1275 COMPLETE_WITH_ATTR(prev2_wd);
1278 /* TODO: also include SRF ? */
1279 else if (pg_strcasecmp(prev_wd, "FROM") == 0)
1280 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv, NULL);
1283 /* Backslash commands */
1284 /* TODO: \dc \dd \dl */
1285 else if (strcmp(prev_wd, "\\connect") == 0 || strcmp(prev_wd, "\\c") == 0)
1286 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
1287 else if (strcmp(prev_wd, "\\d") == 0 || strcmp(prev_wd, "\\d+") == 0)
1288 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tisv, NULL);
1289 else if (strcmp(prev_wd, "\\da") == 0)
1290 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
1291 else if (strcmp(prev_wd, "\\dD") == 0)
1292 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
1293 else if (strcmp(prev_wd, "\\df") == 0 || strcmp(prev_wd, "\\df+") == 0)
1294 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
1295 else if (strcmp(prev_wd, "\\di") == 0 || strcmp(prev_wd, "\\di+") == 0)
1296 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
1297 else if (strcmp(prev_wd, "\\dn") == 0)
1298 COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
1299 else if (strcmp(prev_wd, "\\dp") == 0 || strcmp(prev_wd, "\\z") == 0)
1300 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv, NULL);
1301 else if (strcmp(prev_wd, "\\ds") == 0 || strcmp(prev_wd, "\\ds+") == 0)
1302 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
1303 else if (strcmp(prev_wd, "\\dS") == 0 || strcmp(prev_wd, "\\dS+") == 0)
1304 COMPLETE_WITH_QUERY(Query_for_list_of_system_relations);
1305 else if (strcmp(prev_wd, "\\dt") == 0 || strcmp(prev_wd, "\\dt+") == 0)
1306 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
1307 else if (strcmp(prev_wd, "\\dT") == 0 || strcmp(prev_wd, "\\dT+") == 0)
1308 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
1309 else if (strcmp(prev_wd, "\\du") == 0)
1310 COMPLETE_WITH_QUERY(Query_for_list_of_users);
1311 else if (strcmp(prev_wd, "\\dv") == 0 || strcmp(prev_wd, "\\dv+") == 0)
1312 COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
1313 else if (strcmp(prev_wd, "\\encoding") == 0)
1314 COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
1315 else if (strcmp(prev_wd, "\\h") == 0 || strcmp(prev_wd, "\\help") == 0)
1316 COMPLETE_WITH_LIST(sql_commands);
1317 else if (strcmp(prev_wd, "\\pset") == 0)
1319 static const char * const my_list[] =
1320 {"format", "border", "expanded",
1321 "null", "fieldsep", "tuples_only", "title", "tableattr", "pager",
1324 COMPLETE_WITH_LIST(my_list);
1326 else if (strcmp(prev_wd, "\\cd") == 0 ||
1327 strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 ||
1328 strcmp(prev_wd, "\\g") == 0 ||
1329 strcmp(prev_wd, "\\i") == 0 || strcmp(prev_wd, "\\include") == 0 ||
1330 strcmp(prev_wd, "\\o") == 0 || strcmp(prev_wd, "\\out") == 0 ||
1331 strcmp(prev_wd, "\\s") == 0 ||
1332 strcmp(prev_wd, "\\w") == 0 || strcmp(prev_wd, "\\write") == 0
1334 matches = completion_matches(text, filename_completion_function);
1338 * Finally, we look through the list of "things", such as TABLE, INDEX
1339 * and check if that was the previous word. If so, execute the query
1340 * to get a list of them.
1346 for (i = 0; words_after_create[i].name; i++)
1348 if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
1350 if (words_after_create[i].query)
1351 COMPLETE_WITH_QUERY(words_after_create[i].query);
1352 else if (words_after_create[i].squery)
1353 COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
1361 * If we still don't have anything to match we have to fabricate some
1362 * sort of default list. If we were to just return NULL, readline
1363 * automatically attempts filename completion, and that's usually no
1366 if (matches == NULL)
1368 COMPLETE_WITH_CONST("");
1369 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
1370 rl_completion_append_character = '\0';
1380 /* Return our Grand List O' Matches */
1386 /* GENERATOR FUNCTIONS
1388 These functions do all the actual work of completing the input. They get
1389 passed the text so far and the count how many times they have been called so
1390 far with the same text.
1391 If you read the above carefully, you'll see that these don't get called
1392 directly but through the readline interface.
1393 The return value is expected to be the full completion of the text, going
1394 through a list each time, or NULL if there are no more matches. The string
1395 will be free()'d by readline, so you must run it through strdup() or
1396 something of that sort.
1399 /* This one gives you one from a list of things you can put after CREATE or DROP
1403 create_command_generator(const char *text, int state)
1405 static int list_index,
1409 /* If this is the first time for this completion, init some values */
1413 string_length = strlen(text);
1416 /* find something that matches */
1417 while ((name = words_after_create[list_index++].name))
1418 if (pg_strncasecmp(name, text, string_length) == 0)
1419 return pg_strdup(name);
1421 /* if nothing matches, return NULL */
1426 /* The following two functions are wrappers for _complete_from_query */
1429 complete_from_query(const char *text, int state)
1431 return _complete_from_query(0, text, state);
1435 complete_from_schema_query(const char *text, int state)
1437 return _complete_from_query(1, text, state);
1441 /* This creates a list of matching things, according to a query pointed to
1442 by completion_charp.
1443 The query can be one of two kinds:
1444 - A simple query which must contain a %d and a %s, which will be replaced
1445 by the string length of the text and the text itself. The query may also
1446 have another %s in it, which will be replaced by the value of
1447 completion_info_charp.
1449 - A schema query used for completion of both schema and relation names;
1450 these are more complex and must contain in the following order:
1451 %d %s %d %s %d %s %s %d %s
1452 where %d is the string length of the text and %s the text itself.
1454 It is assumed that strings should be escaped to become SQL literals
1455 (that is, what is in the query is actually ... '%s' ...)
1457 See top of file for examples of both kinds of query.
1461 _complete_from_query(int is_schema_query, const char *text, int state)
1463 static int list_index,
1465 static PGresult *result = NULL;
1468 * If this is the first time for this completion, we fetch a list of
1469 * our "things" from the backend.
1473 PQExpBufferData query_buffer;
1478 string_length = strlen(text);
1480 /* Free any prior result */
1484 /* Set up suitably-escaped copies of textual inputs */
1487 e_text = pg_malloc(strlen(text) * 2 + 1);
1488 PQescapeString(e_text, text, strlen(text));
1493 if (completion_info_charp)
1497 charp_len = strlen(completion_info_charp);
1498 e_info_charp = pg_malloc(charp_len * 2 + 1);
1499 PQescapeString(e_info_charp, completion_info_charp,
1503 e_info_charp = NULL;
1505 initPQExpBuffer(&query_buffer);
1507 if (is_schema_query)
1509 /* completion_squery gives us the pieces to assemble */
1510 const char *qualresult = completion_squery->qualresult;
1512 if (qualresult == NULL)
1513 qualresult = completion_squery->result;
1515 /* Get unqualified names matching the input-so-far */
1516 appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ",
1517 completion_squery->result,
1518 completion_squery->catname);
1519 if (completion_squery->selcondition)
1520 appendPQExpBuffer(&query_buffer, "%s AND ",
1521 completion_squery->selcondition);
1522 appendPQExpBuffer(&query_buffer, "%s AND ",
1523 completion_squery->viscondition);
1524 appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'",
1525 completion_squery->result,
1526 string_length, e_text);
1528 * When fetching relation names, suppress system catalogs unless
1529 * the input-so-far begins with "pg_". This is a compromise
1530 * between not offering system catalogs for completion at all,
1531 * and having them swamp the result when the input is just "p".
1533 if (strcmp(completion_squery->catname,
1534 "pg_catalog.pg_class c") == 0 &&
1535 strncmp(text, "pg_", 3) != 0)
1537 appendPQExpBuffer(&query_buffer,
1538 " AND c.relnamespace <> (SELECT oid FROM"
1539 " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')");
1543 * Add in matching schema names, but only if there is more than
1544 * one potential match among schema names.
1546 appendPQExpBuffer(&query_buffer, "\nUNION\n"
1547 "SELECT pg_catalog.quote_ident(n.nspname) || '.' "
1548 "FROM pg_catalog.pg_namespace n "
1549 "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'",
1550 string_length, e_text);
1551 appendPQExpBuffer(&query_buffer,
1552 " AND (SELECT pg_catalog.count(*)"
1553 " FROM pg_catalog.pg_namespace"
1554 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
1555 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1",
1556 string_length, e_text);
1559 * Add in matching qualified names, but only if there is exactly
1560 * one schema matching the input-so-far.
1562 appendPQExpBuffer(&query_buffer, "\nUNION\n"
1563 "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s "
1564 "FROM %s, pg_catalog.pg_namespace n "
1565 "WHERE %s = n.oid AND ",
1567 completion_squery->catname,
1568 completion_squery->namespace);
1569 if (completion_squery->selcondition)
1570 appendPQExpBuffer(&query_buffer, "%s AND ",
1571 completion_squery->selcondition);
1572 appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'",
1574 string_length, e_text);
1575 /* This condition exploits the single-matching-schema rule to speed up the query */
1576 appendPQExpBuffer(&query_buffer,
1577 " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) ="
1578 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)",
1579 string_length, e_text);
1580 appendPQExpBuffer(&query_buffer,
1581 " AND (SELECT pg_catalog.count(*)"
1582 " FROM pg_catalog.pg_namespace"
1583 " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) ="
1584 " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1",
1585 string_length, e_text);
1587 /* If an addon query was provided, use it */
1588 if (completion_charp)
1589 appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
1593 /* completion_charp is an sprintf-style format string */
1594 appendPQExpBuffer(&query_buffer, completion_charp,
1595 string_length, e_text, e_info_charp);
1598 /* Limit the number of records in the result */
1599 appendPQExpBuffer(&query_buffer, "\nLIMIT %d",
1600 completion_max_records);
1602 result = exec_query(query_buffer.data);
1604 termPQExpBuffer(&query_buffer);
1612 /* Find something that matches */
1613 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
1617 while (list_index < PQntuples(result) &&
1618 (item = PQgetvalue(result, list_index++, 0)))
1619 if (pg_strncasecmp(text, item, string_length) == 0)
1620 return pg_strdup(item);
1623 /* If nothing matches, free the db structure and return null */
1630 /* This function returns in order one of a fixed, NULL pointer terminated list
1631 of strings (if matching). This can be used if there are only a fixed number
1632 SQL words that can appear at certain spot.
1635 complete_from_list(const char *text, int state)
1637 static int string_length,
1640 static bool casesensitive;
1643 /* need to have a list */
1644 psql_assert(completion_charpp);
1646 /* Initialization */
1650 string_length = strlen(text);
1651 casesensitive = true;
1655 while ((item = completion_charpp[list_index++]))
1657 /* First pass is case sensitive */
1658 if (casesensitive && strncmp(text, item, string_length) == 0)
1661 return pg_strdup(item);
1664 /* Second pass is case insensitive, don't bother counting matches */
1665 if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0)
1666 return pg_strdup(item);
1670 * No matches found. If we're not case insensitive already, lets
1671 * switch to being case insensitive and try again
1673 if (casesensitive && matches == 0)
1675 casesensitive = false;
1678 return (complete_from_list(text, state));
1681 /* If no more matches, return null. */
1686 /* This function returns one fixed string the first time even if it doesn't
1687 match what's there, and nothing the second time. This should be used if there
1688 is only one possibility that can appear at a certain spot, so misspellings
1689 will be overwritten.
1690 The string to be passed must be in completion_charp.
1693 complete_from_const(const char *text, int state)
1695 (void) text; /* We don't care about what was entered
1698 psql_assert(completion_charp);
1700 return pg_strdup(completion_charp);
1707 /* HELPER FUNCTIONS */
1711 * Execute a query and report any errors. This should be the preferred way of
1712 * talking to the database in this file.
1715 exec_query(const char *query)
1719 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
1722 result = PQexec(pset.db, query);
1724 if (result != NULL && PQresultStatus(result) != PGRES_TUPLES_OK)
1727 psql_error("tab completion: %s failed - %s\n",
1728 query, PQresStatus(PQresultStatus(result)));
1739 /* Return the word (space delimited) before point. Set skip > 0 to skip that
1740 many words; e.g. skip=1 finds the word before the previous one.
1743 previous_word(int point, int skip)
1753 /* first we look for a space before the current word */
1754 for (i = point; i >= 0; i--)
1755 if (rl_line_buffer[i] == ' ')
1758 /* now find the first non-space which then constitutes the end */
1760 if (rl_line_buffer[i] != ' ')
1767 * If no end found we return null, because there is no word before
1774 * Otherwise we now look for the start. The start is either the
1775 * last character before any space going backwards from the end,
1776 * or it's simply character 0
1778 for (start = end; start > 0; start--)
1780 if (rl_line_buffer[start] == '"')
1781 inquotes = !inquotes;
1782 if ((rl_line_buffer[start - 1] == ' ') && inquotes == 0)
1790 s = pg_malloc(end - start + 2);
1792 strncpy(s, &rl_line_buffer[start], end - start + 1);
1793 s[end - start + 1] = '\0';
1803 * Surround a string with single quotes. This works for both SQL and
1804 * psql internal. Currently disabled because it is reported not to
1805 * cooperate with certain versions of readline.
1808 quote_file_name(char *text, int match_type, char *quote_pointer)
1813 (void) quote_pointer; /* not used */
1815 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
1816 s = pg_malloc(length);
1818 strcpy(s + 1, text);
1819 if (match_type == SINGLE_MATCH)
1820 s[length - 2] = '\'';
1821 s[length - 1] = '\0';
1828 dequote_file_name(char *text, char quote_char)
1834 return pg_strdup(text);
1836 length = strlen(text);
1837 s = pg_malloc(length - 2 + 1);
1838 strncpy(s, text +1, length - 2);
1845 #endif /* USE_READLINE */