2 * psql - the PostgreSQL interactive terminal
4 * Copyright 2000-2002 by PostgreSQL Global Development Group
6 * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.69 2002/11/21 00:42:19 tgl 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 tuples returned gets limited, in most default
19 * installations to 101, 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 things 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"
49 /* If we don't have this, we might as well forget about the whole thing: */
53 #ifdef USE_ASSERT_CHECKING
62 #ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION
63 #define filename_completion_function rl_filename_completion_function
65 /* missing in some header files */
66 extern char *filename_completion_function();
69 #ifdef HAVE_RL_COMPLETION_MATCHES
70 #define completion_matches(x, y) rl_completion_matches((x), ((rl_compentry_func_t *)(y)))
74 #define ERROR_QUERY_TOO_LONG /* empty */
77 /* Forward declaration of functions */
78 static char **psql_completion(char *text, int start, int end);
79 static char *create_command_generator(char *text, int state);
80 static char *complete_from_query(char *text, int state);
81 static char *complete_from_const(char *text, int state);
82 static char *complete_from_list(char *text, int state);
84 static PGresult *exec_query(char *query);
85 char *quote_file_name(char *text, int match_type, char *quote_pointer);
87 /*static char * dequote_file_name(char *text, char quote_char);*/
88 static char *previous_word(int point, int skip);
90 /* These variables are used to pass information into the completion functions.
91 Realizing that this is the cardinal sin of programming, I don't see a better
93 char *completion_charp; /* if you need to pass a string */
94 char **completion_charpp; /* if you need to pass a list of strings */
95 char *completion_info_charp; /* if you need to pass another
98 /* Store how many records from a database query we want to return at most
99 (implemented via SELECT ... LIMIT xx). */
100 static int completion_max_records;
103 /* Initialize the readline library for our purposes. */
105 initialize_readline(void)
107 rl_readline_name = pset.progname;
108 rl_attempted_completion_function = (void *) psql_completion;
110 rl_basic_word_break_characters = "\t\n@$><=;|&{( ";
112 completion_max_records = 100;
115 * There is a variable rl_completion_query_items for this but
116 * apparently it's not defined everywhere.
122 * Queries to get lists of names of various kinds of things, possibly
123 * restricted to names matching a partially entered name. In these queries,
124 * the %s will be replaced by the text entered so far, the %d by its length.
127 #define Query_for_list_of_tables "SELECT relname FROM pg_catalog.pg_class WHERE (relkind='r' or relkind='v') and substr(relname,1,%d)='%s' and pg_catalog.pg_table_is_visible(oid)"
128 #define Query_for_list_of_indexes "SELECT relname FROM pg_catalog.pg_class WHERE relkind='i' and substr(relname,1,%d)='%s' and pg_catalog.pg_table_is_visible(oid)"
129 #define Query_for_list_of_databases "SELECT datname FROM pg_catalog.pg_database WHERE substr(datname,1,%d)='%s'"
130 #define Query_for_list_of_attributes "SELECT a.attname FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c WHERE c.oid = a.attrelid and a.attnum>0 and not a.attisdropped and substr(a.attname,1,%d)='%s' and c.relname='%s' and pg_catalog.pg_table_is_visible(c.oid)"
131 #define Query_for_list_of_users "SELECT usename FROM pg_catalog.pg_user WHERE substr(usename,1,%d)='%s'"
133 /* This is a list of all "things" in Pgsql, which can show up after CREATE or
134 DROP; and there is also a query to get a list of them.
142 pgsql_thing_t words_after_create[] = {
143 {"AGGREGATE", "SELECT DISTINCT proname FROM pg_catalog.pg_proc WHERE proisagg AND substr(proname,1,%d)='%s'"},
144 {"CAST", NULL}, /* Casts have complex structures for namees, so skip it */
145 {"CONVERSION", "SELECT conname FROM pg_catalog.pg_conversion WHERE substr(conname,1,%d)='%s'"},
146 {"DATABASE", Query_for_list_of_databases},
147 {"DOMAIN", "SELECT typname FROM pg_catalog.pg_type WHERE typtype = 'd' AND substr(typname,1,%d)='%s'"},
148 {"FUNCTION", "SELECT DISTINCT proname FROM pg_catalog.pg_proc WHERE substr(proname,1,%d)='%s'"},
149 {"GROUP", "SELECT groname FROM pg_catalog.pg_group WHERE substr(groname,1,%d)='%s'"},
150 {"LANGUAGE", "SELECT lanname FROM pg_catalog.pg_language WHERE substr(lanname,1,%d)='%s'"},
151 {"INDEX", Query_for_list_of_indexes},
152 {"OPERATOR", NULL}, /* Querying for this is probably not such
154 {"RULE", "SELECT rulename FROM pg_catalog.pg_rules WHERE substr(rulename,1,%d)='%s'"},
155 {"SCHEMA", "SELECT nspname FROM pg_catalog.pg_namespace WHERE substr(nspname,1,%d)='%s'"},
156 {"SEQUENCE", "SELECT relname FROM pg_catalog.pg_class WHERE relkind='S' and substr(relname,1,%d)='%s'"},
157 {"TABLE", Query_for_list_of_tables},
158 {"TEMP", NULL}, /* for CREATE TEMP TABLE ... */
159 {"TRIGGER", "SELECT tgname FROM pg_catalog.pg_trigger WHERE substr(tgname,1,%d)='%s'"},
160 {"TYPE", "SELECT typname FROM pg_catalog.pg_type WHERE substr(typname,1,%d)='%s'"},
161 {"UNIQUE", NULL}, /* for CREATE UNIQUE INDEX ... */
162 {"USER", Query_for_list_of_users},
163 {"VIEW", "SELECT viewname FROM pg_catalog.pg_views WHERE substr(viewname,1,%d)='%s'"},
164 {NULL, NULL} /* end of list */
168 /* A couple of macros to ease typing. You can use these to complete the given
170 1) The results from a query you pass it. (Perhaps one of those above?)
171 2) The items from a null-pointer-terminated list.
173 4) The list of attributes to the given table.
175 #define COMPLETE_WITH_QUERY(query) \
176 do { completion_charp = query; matches = completion_matches(text, complete_from_query); } while(0)
177 #define COMPLETE_WITH_LIST(list) \
178 do { completion_charpp = list; matches = completion_matches(text, complete_from_list); } while(0)
179 #define COMPLETE_WITH_CONST(string) \
180 do { completion_charp = string; matches = completion_matches(text, complete_from_const); } while(0)
181 #define COMPLETE_WITH_ATTR(table) \
182 do {completion_charp = Query_for_list_of_attributes; completion_info_charp = table; matches = completion_matches(text, complete_from_query); } while(0)
185 /* The completion function. Acc. to readline spec this gets passed the text
186 entered to far and its start and end in the readline buffer. The return value
187 is some partially obscure list format that can be generated by the readline
188 libraries completion_matches() function, so we don't have to worry about it.
191 psql_completion(char *text, int start, int end)
193 /* This is the variable we'll return. */
194 char **matches = NULL;
196 /* These are going to contain some scannage of the input line. */
202 static char *sql_commands[] = {
203 "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT",
204 "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", "DELETE", "DROP", "EXECUTE",
205 "EXPLAIN", "FETCH", "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY",
206 "PREPARE", "REINDEX", "RESET", "REVOKE", "ROLLBACK", "SELECT", "SET", "SHOW",
207 "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", NULL
210 static char *pgsql_variables[] = {
211 /* these SET arguments are known in gram.y */
215 "TRANSACTION ISOLATION LEVEL",
216 /* these are treated in backend/commands/variable.c */
224 * the rest should match USERSET entries in
225 * backend/utils/misc/guc.c
227 "australian_timezones",
228 "authentication_timeout",
230 "checkpoint_segments",
231 "checkpoint_timeout",
232 "client_min_messages",
235 "cpu_index_tuple_cost",
240 "debug_pretty_print",
243 "debug_print_rewritten",
244 "default_statistics_target",
245 "default_transaction_isolation",
246 "dynamic_library_path",
247 "effective_cache_size",
256 "explain_pretty_print",
257 "extra_float_digits",
265 "geqo_selection_bias",
268 "krb_server_keyfile",
275 "log_min_error_statement",
281 "max_files_per_process",
284 "max_locks_per_transaction",
285 "password_encryption",
292 "log_executor_stats",
296 "log_statement_stats",
303 "stats_command_string",
304 "stats_reset_on_server_start",
306 "stats_start_collector",
307 "superuser_reserved_connections",
313 "transform_null_equals",
314 "unix_socket_directory",
316 "unix_socket_permissions",
325 static char *backslash_commands[] = {
326 "\\a", "\\connect", "\\C", "\\cd", "\\copy", "\\copyright",
327 "\\d", "\\da", "\\dd", "\\dD", "\\df", "\\di", "\\dl", "\\do",
328 "\\dp", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv","\\du",
329 "\\e", "\\echo", "\\encoding",
330 "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
331 "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
332 "\\o", "\\p", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\t", "\\T",
333 "\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
336 (void) end; /* not used */
338 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
339 rl_completion_append_character = ' ';
342 /* Clear a few things. */
343 completion_charp = NULL;
344 completion_charpp = NULL;
345 completion_info_charp = NULL;
348 * Scan the input line before our current position for the last four
349 * words. According to those we'll make some smart decisions on what
350 * the user is probably intending to type. TODO: Use strtokx() to do
353 prev_wd = previous_word(start, 0);
354 prev2_wd = previous_word(start, 1);
355 prev3_wd = previous_word(start, 2);
356 prev4_wd = previous_word(start, 3);
358 /* If a backslash command was started, continue */
360 COMPLETE_WITH_LIST(backslash_commands);
362 /* If no previous word, suggest one of the basic sql commands */
364 COMPLETE_WITH_LIST(sql_commands);
367 /* complete with something you can create or drop */
368 else if (strcasecmp(prev_wd, "CREATE") == 0 || strcasecmp(prev_wd, "DROP") == 0)
369 matches = completion_matches(text, create_command_generator);
372 /* complete with what you can alter (TABLE, GROUP, USER, ...) */
373 else if (strcasecmp(prev_wd, "ALTER") == 0)
375 char *list_ALTER[] = {"DATABASE", "GROUP", "SCHEMA", "TABLE", "TRIGGER", "USER", NULL};
377 COMPLETE_WITH_LIST(list_ALTER);
380 /* ALTER DATABASE <name> */
381 else if (strcasecmp(prev3_wd, "ALTER") == 0 && strcasecmp(prev2_wd, "DATABASE") == 0)
383 char *list_ALTERDATABASE[] = {"RESET", "SET", NULL};
385 COMPLETE_WITH_LIST(list_ALTERDATABASE);
387 /* ALTER TRIGGER <name>, add ON */
388 else if (strcasecmp(prev3_wd, "ALTER") == 0 && strcasecmp(prev2_wd, "TRIGGER") == 0)
389 COMPLETE_WITH_CONST("ON");
392 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
394 else if (strcasecmp(prev4_wd, "ALTER") == 0 && strcasecmp(prev3_wd, "TRIGGER") == 0
395 && strcasecmp(prev_wd, "ON") == 0)
396 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
399 * If we detect ALTER TABLE <name>, suggest either ADD, ALTER, or
402 else if (strcasecmp(prev3_wd, "ALTER") == 0 && strcasecmp(prev2_wd, "TABLE") == 0)
404 char *list_ALTER2[] = {"ADD", "ALTER", "RENAME", NULL};
406 COMPLETE_WITH_LIST(list_ALTER2);
408 /* If we have TABLE <sth> ALTER|RENAME, provide list of columns */
409 else if (strcasecmp(prev3_wd, "TABLE") == 0 &&
410 (strcasecmp(prev_wd, "ALTER") == 0 || strcasecmp(prev_wd, "RENAME") == 0))
411 COMPLETE_WITH_ATTR(prev2_wd);
413 /* complete ALTER GROUP <foo> with ADD or DROP */
414 else if (strcasecmp(prev3_wd, "ALTER") == 0 && strcasecmp(prev2_wd, "GROUP") == 0)
416 char *list_ALTERGROUP[] = {"ADD", "DROP", NULL};
418 COMPLETE_WITH_LIST(list_ALTERGROUP);
420 /* complete ALTER GROUP <foo> ADD|DROP with USER */
421 else if (strcasecmp(prev4_wd, "ALTER") == 0 && strcasecmp(prev3_wd, "GROUP") == 0
422 && (strcasecmp(prev_wd, "ADD") == 0 || strcasecmp(prev_wd, "DROP") == 0))
423 COMPLETE_WITH_CONST("USER");
424 /* complete {ALTER} GROUP <foo> ADD|DROP USER with a user name */
425 else if (strcasecmp(prev4_wd, "GROUP") == 0
426 && (strcasecmp(prev2_wd, "ADD") == 0 || strcasecmp(prev2_wd, "DROP") == 0)
427 && strcasecmp(prev_wd, "USER") == 0)
428 COMPLETE_WITH_QUERY(Query_for_list_of_users);
431 /* If the previous word is ANALYZE, produce list of tables. */
432 else if (strcasecmp(prev_wd, "ANALYZE") == 0)
433 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
434 /* If we have ANALYZE <table>, complete with semicolon. */
435 else if (strcasecmp(prev2_wd, "ANALYZE") == 0)
436 COMPLETE_WITH_CONST(";");
439 /* If the previous word is CLUSTER, produce list of indexes. */
440 else if (strcasecmp(prev_wd, "CLUSTER") == 0)
441 COMPLETE_WITH_QUERY(Query_for_list_of_indexes);
442 /* If we have CLUSTER <sth>, then add "ON" */
443 else if (strcasecmp(prev2_wd, "CLUSTER") == 0)
444 COMPLETE_WITH_CONST("ON");
447 * If we have CLUSTER <sth> ON, then add the correct tablename as
450 else if (strcasecmp(prev3_wd, "CLUSTER") == 0 && strcasecmp(prev_wd, "ON") == 0)
452 char query_buffer[BUF_SIZE]; /* Some room to build
455 if (snprintf(query_buffer, BUF_SIZE,
456 "SELECT c1.relname FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid and c2.relname='%s' and pg_catalog.pg_table_is_visible(c2.oid)",
458 ERROR_QUERY_TOO_LONG;
460 COMPLETE_WITH_QUERY(query_buffer);
464 else if (strcasecmp(prev_wd, "COMMENT") == 0)
465 COMPLETE_WITH_CONST("ON");
466 else if (strcasecmp(prev2_wd, "COMMENT") == 0 && strcasecmp(prev_wd, "ON") == 0)
468 char *list_COMMENT[] =
469 {"DATABASE", "INDEX", "RULE", "SCHEMA", "SEQUENCE", "TABLE", "TYPE", "VIEW",
470 "COLUMN", "AGGREGATE", "FUNCTION", "OPERATOR", "TRIGGER", "CONSTRAINT",
473 COMPLETE_WITH_LIST(list_COMMENT);
475 else if (strcasecmp(prev4_wd, "COMMENT") == 0 && strcasecmp(prev3_wd, "ON") == 0)
476 COMPLETE_WITH_CONST("IS");
481 * If we have COPY [BINARY] (which you'd have to type yourself), offer
482 * list of tables (Also cover the analogous backslash command)
484 else if (strcasecmp(prev_wd, "COPY") == 0 ||
485 strcasecmp(prev_wd, "\\copy") == 0 ||
486 (strcasecmp(prev2_wd, "COPY") == 0 && strcasecmp(prev_wd, "BINARY") == 0))
487 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
488 /* If we have COPY|BINARY <sth>, complete it with "TO" or "FROM" */
489 else if (strcasecmp(prev2_wd, "COPY") == 0 ||
490 strcasecmp(prev2_wd, "\\copy") == 0 ||
491 strcasecmp(prev2_wd, "BINARY") == 0)
493 char *list_FROMTO[] = {"FROM", "TO", NULL};
495 COMPLETE_WITH_LIST(list_FROMTO);
499 /* First off we complete CREATE UNIQUE with "INDEX" */
500 else if (strcasecmp(prev2_wd, "CREATE") == 0 && strcasecmp(prev_wd, "UNIQUE") == 0)
501 COMPLETE_WITH_CONST("INDEX");
502 /* If we have CREATE|UNIQUE INDEX <sth>, then add "ON" */
503 else if (strcasecmp(prev2_wd, "INDEX") == 0 &&
504 (strcasecmp(prev3_wd, "CREATE") == 0 || strcasecmp(prev3_wd, "UNIQUE") == 0))
505 COMPLETE_WITH_CONST("ON");
506 /* Complete ... INDEX <name> ON with a list of tables */
507 else if ((strcasecmp(prev3_wd, "INDEX") == 0 && strcasecmp(prev_wd, "ON") == 0) || (0))
508 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
511 * Complete INDEX <name> ON <table> with a list of table columns
512 * (which should really be in parens)
514 else if (strcasecmp(prev4_wd, "INDEX") == 0 && strcasecmp(prev2_wd, "ON") == 0)
515 COMPLETE_WITH_ATTR(prev_wd);
516 /* same if you put in USING */
517 else if ((strcasecmp(prev4_wd, "ON") == 0 && strcasecmp(prev2_wd, "USING") == 0))
518 COMPLETE_WITH_ATTR(prev3_wd);
519 /* Complete USING with an index method */
520 else if (strcasecmp(prev_wd, "USING") == 0)
522 char *index_mth[] = {"BTREE", "RTREE", "HASH", "GIST", NULL};
524 COMPLETE_WITH_LIST(index_mth);
528 /* Complete "CREATE RULE <sth>" with "AS" */
529 else if (strcasecmp(prev3_wd, "CREATE") == 0 && strcasecmp(prev2_wd, "RULE") == 0)
530 COMPLETE_WITH_CONST("AS");
531 /* Complete "CREATE RULE <sth> AS with "ON" */
532 else if (strcasecmp(prev4_wd, "CREATE") == 0 &&
533 strcasecmp(prev3_wd, "RULE") == 0 &&
534 strcasecmp(prev_wd, "AS") == 0)
535 COMPLETE_WITH_CONST("ON");
536 /* Complete "RULE * AS ON" with SELECT|UPDATE|DELETE|INSERT */
537 else if (strcasecmp(prev4_wd, "RULE") == 0 &&
538 strcasecmp(prev2_wd, "AS") == 0 &&
539 strcasecmp(prev_wd, "ON") == 0)
541 char *rule_events[] = {"SELECT", "UPDATE", "INSERT", "DELETE", NULL};
543 COMPLETE_WITH_LIST(rule_events);
545 /* Complete "AS ON <sth with a 'T' :)>" with a "TO" */
546 else if (strcasecmp(prev3_wd, "AS") == 0 &&
547 strcasecmp(prev2_wd, "ON") == 0 &&
548 (toupper((unsigned char) prev_wd[4]) == 'T' ||
549 toupper((unsigned char) prev_wd[5]) == 'T'))
550 COMPLETE_WITH_CONST("TO");
551 /* Complete "AS ON <sth> TO" with a table name */
552 else if (strcasecmp(prev4_wd, "AS") == 0 &&
553 strcasecmp(prev3_wd, "ON") == 0 &&
554 strcasecmp(prev_wd, "TO") == 0)
555 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
558 /* Complete CREATE TEMP with "TABLE" */
559 else if (strcasecmp(prev2_wd, "CREATE") == 0 && strcasecmp(prev_wd, "TEMP") == 0)
560 COMPLETE_WITH_CONST("TABLE");
563 /* is on the agenda . . . */
566 /* Complete "CREATE VIEW <name>" with "AS" */
567 else if (strcasecmp(prev3_wd, "CREATE") == 0 && strcasecmp(prev2_wd, "VIEW") == 0)
568 COMPLETE_WITH_CONST("AS");
569 /* Complete "CREATE VIEW <sth> AS with "SELECT" */
570 else if (strcasecmp(prev4_wd, "CREATE") == 0 &&
571 strcasecmp(prev3_wd, "VIEW") == 0 &&
572 strcasecmp(prev_wd, "AS") == 0)
573 COMPLETE_WITH_CONST("SELECT");
578 * Complete DELETE with FROM (only if the word before that is not "ON"
579 * (cf. rules) or "BEFORE" or "AFTER" (cf. triggers) or GRANT)
581 else if (strcasecmp(prev_wd, "DELETE") == 0 &&
582 !(strcasecmp(prev2_wd, "ON") == 0 ||
583 strcasecmp(prev2_wd, "GRANT") == 0 ||
584 strcasecmp(prev2_wd, "BEFORE") == 0 ||
585 strcasecmp(prev2_wd, "AFTER") == 0))
586 COMPLETE_WITH_CONST("FROM");
587 /* Complete DELETE FROM with a list of tables */
588 else if (strcasecmp(prev2_wd, "DELETE") == 0 && strcasecmp(prev_wd, "FROM") == 0)
589 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
590 /* Complete DELETE FROM <table> with "WHERE" (perhaps a safe idea?) */
591 else if (strcasecmp(prev3_wd, "DELETE") == 0 && strcasecmp(prev2_wd, "FROM") == 0)
592 COMPLETE_WITH_CONST("WHERE");
597 * Complete EXPLAIN [VERBOSE] (which you'd have to type yourself) with
598 * the list of SQL commands
600 else if (strcasecmp(prev_wd, "EXPLAIN") == 0 ||
601 (strcasecmp(prev2_wd, "EXPLAIN") == 0 && strcasecmp(prev_wd, "VERBOSE") == 0))
602 COMPLETE_WITH_LIST(sql_commands);
605 /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
606 else if (strcasecmp(prev_wd, "FETCH") == 0 || strcasecmp(prev_wd, "MOVE") == 0)
608 char *list_FETCH1[] = {"FORWARD", "BACKWARD", "RELATIVE", NULL};
610 COMPLETE_WITH_LIST(list_FETCH1);
612 /* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
613 else if (strcasecmp(prev2_wd, "FETCH") == 0 || strcasecmp(prev2_wd, "MOVE") == 0)
615 char *list_FETCH2[] = {"ALL", "NEXT", "PRIOR", NULL};
617 COMPLETE_WITH_LIST(list_FETCH2);
621 * Complete FETCH <sth1> <sth2> with "FROM" or "TO". (Is there a
622 * difference? If not, remove one.)
624 else if (strcasecmp(prev3_wd, "FETCH") == 0 || strcasecmp(prev3_wd, "MOVE") == 0)
626 char *list_FROMTO[] = {"FROM", "TO", NULL};
628 COMPLETE_WITH_LIST(list_FROMTO);
632 /* Complete GRANT/REVOKE with a list of privileges */
633 else if (strcasecmp(prev_wd, "GRANT") == 0 || strcasecmp(prev_wd, "REVOKE") == 0)
635 char *list_privileg[] = {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES", "TRIGGER", "CREATE", "TEMPORARY", "EXECUTE", "USAGE", "ALL", NULL};
637 COMPLETE_WITH_LIST(list_privileg);
639 /* Complete GRANT/REVOKE <sth> with "ON" */
640 else if (strcasecmp(prev2_wd, "GRANT") == 0 || strcasecmp(prev2_wd, "REVOKE") == 0)
641 COMPLETE_WITH_CONST("ON");
644 * Complete GRANT/REVOKE <sth> ON with a list of tables, views,
645 * sequences, and indexes
647 * XXX should also offer DATABASE, FUNCTION, LANGUAGE, SCHEMA here
649 else if ((strcasecmp(prev3_wd, "GRANT") == 0 || strcasecmp(prev3_wd, "REVOKE") == 0) &&
650 strcasecmp(prev_wd, "ON") == 0)
651 COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_class "
652 "WHERE relkind in ('r','i','S','v') AND "
653 "substr(relname,1,%d)='%s' AND pg_catalog.pg_table_is_visible(oid)");
654 /* Complete "GRANT * ON * " with "TO" */
655 else if (strcasecmp(prev4_wd, "GRANT") == 0 && strcasecmp(prev2_wd, "ON") == 0)
656 COMPLETE_WITH_CONST("TO");
657 /* Complete "REVOKE * ON * " with "FROM" */
658 else if (strcasecmp(prev4_wd, "REVOKE") == 0 && strcasecmp(prev2_wd, "ON") == 0)
659 COMPLETE_WITH_CONST("FROM");
662 * TODO: to complete with user name we need prev5_wd -- wait for a
663 * more general solution there
667 /* Complete INSERT with "INTO" */
668 else if (strcasecmp(prev_wd, "INSERT") == 0)
669 COMPLETE_WITH_CONST("INTO");
670 /* Complete INSERT INTO with table names */
671 else if (strcasecmp(prev2_wd, "INSERT") == 0 && strcasecmp(prev_wd, "INTO") == 0)
672 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
673 /* Complete "INSERT INTO <table> (" with attribute names */
674 else if (rl_line_buffer[start - 1] == '(' && strcasecmp(prev3_wd, "INSERT") == 0 && strcasecmp(prev2_wd, "INTO") == 0)
675 COMPLETE_WITH_ATTR(prev_wd);
678 * Complete INSERT INTO <table> with "VALUES" or "SELECT" or "DEFAULT
681 else if (strcasecmp(prev3_wd, "INSERT") == 0 && strcasecmp(prev2_wd, "INTO") == 0)
683 char *list_INSERT[] = {"DEFAULT VALUES", "SELECT", "VALUES", NULL};
685 COMPLETE_WITH_LIST(list_INSERT);
687 /* Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" */
688 else if (strcasecmp(prev4_wd, "INSERT") == 0 && strcasecmp(prev3_wd, "INTO") == 0 &&
689 prev_wd[strlen(prev_wd) - 1] == ')')
691 char *list_INSERT[] = {"SELECT", "VALUES", NULL};
693 COMPLETE_WITH_LIST(list_INSERT);
696 /* Insert an open parenthesis after "VALUES" */
697 else if (strcasecmp(prev_wd, "VALUES") == 0 && strcasecmp(prev2_wd, "DEFAULT") != 0)
698 COMPLETE_WITH_CONST("(");
701 /* Complete LOCK [TABLE] with a list of tables */
702 else if ((strcasecmp(prev_wd, "LOCK") == 0) ||
703 (strcasecmp(prev_wd, "TABLE") == 0 && strcasecmp(prev2_wd, "LOCK")))
704 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
706 /* For the following, handle the case of a single table only for now */
708 /* Complete LOCK [TABLE] <table> with "IN" */
709 else if ((strcasecmp(prev2_wd, "LOCK") == 0 && strcasecmp(prev_wd, "TABLE")) ||
710 (strcasecmp(prev2_wd, "TABLE") == 0 && strcasecmp(prev3_wd, "LOCK") == 0))
711 COMPLETE_WITH_CONST("IN");
713 /* Complete LOCK [TABLE] <table> IN with a lock mode */
714 else if (strcasecmp(prev_wd, "IN") == 0 &&
715 (strcasecmp(prev3_wd, "LOCK") == 0 ||
716 (strcasecmp(prev3_wd, "TABLE") == 0 && strcasecmp(prev3_wd, "LOCK"))))
718 char *lock_modes[] = {"ACCESS SHARE MODE", "ROW SHARE MODE", "ROW EXCLUSIVE MODE",
719 "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE", "SHARE ROW EXCLUSIVE MODE",
720 "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE", NULL};
722 COMPLETE_WITH_LIST(lock_modes);
726 else if (strcasecmp(prev_wd, "NOTIFY") == 0)
727 COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_listener WHERE substr(relname,1,%d)='%s'");
730 else if (strcasecmp(prev_wd, "REINDEX") == 0)
732 char *list_REINDEX[] = {"TABLE", "DATABASE", "INDEX", NULL};
734 COMPLETE_WITH_LIST(list_REINDEX);
736 else if (strcasecmp(prev2_wd, "REINDEX") == 0)
738 if (strcasecmp(prev_wd, "TABLE") == 0)
739 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
740 else if (strcasecmp(prev_wd, "DATABASE") == 0)
741 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
742 else if (strcasecmp(prev_wd, "INDEX") == 0)
743 COMPLETE_WITH_QUERY(Query_for_list_of_indexes);
749 /* SET, RESET, SHOW */
750 /* Complete with a variable name */
751 else if ((strcasecmp(prev_wd, "SET") == 0 && strcasecmp(prev3_wd, "UPDATE") != 0) ||
752 strcasecmp(prev_wd, "RESET") == 0 ||
753 strcasecmp(prev_wd, "SHOW") == 0)
754 COMPLETE_WITH_LIST(pgsql_variables);
755 /* Complete "SET TRANSACTION ISOLOLATION LEVEL" */
756 else if (strcasecmp(prev2_wd, "SET") == 0 && strcasecmp(prev_wd, "TRANSACTION") == 0)
757 COMPLETE_WITH_CONST("ISOLATION");
758 else if (strcasecmp(prev3_wd, "SET") == 0 &&
759 strcasecmp(prev2_wd, "TRANSACTION") == 0 &&
760 strcasecmp(prev_wd, "ISOLATION") == 0)
761 COMPLETE_WITH_CONST("LEVEL");
762 else if ((strcasecmp(prev4_wd, "SET") == 0 || strcasecmp(prev4_wd, "AS") == 0) &&
763 strcasecmp(prev3_wd, "TRANSACTION") == 0 &&
764 strcasecmp(prev2_wd, "ISOLATION") == 0 &&
765 strcasecmp(prev_wd, "LEVEL") == 0)
767 char *my_list[] = {"READ", "SERIALIZABLE", NULL};
769 COMPLETE_WITH_LIST(my_list);
771 else if (strcasecmp(prev4_wd, "TRANSACTION") == 0 &&
772 strcasecmp(prev3_wd, "ISOLATION") == 0 &&
773 strcasecmp(prev2_wd, "LEVEL") == 0 &&
774 strcasecmp(prev_wd, "READ") == 0)
775 COMPLETE_WITH_CONST("COMMITTED");
776 /* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
777 else if (strcasecmp(prev3_wd, "SET") == 0 && strcasecmp(prev2_wd, "CONSTRAINTS") == 0)
779 char *constraint_list[] = {"DEFERRED", "IMMEDIATE", NULL};
781 COMPLETE_WITH_LIST(constraint_list);
783 /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
784 else if (strcasecmp(prev2_wd, "SET") == 0 && strcasecmp(prev_wd, "SESSION") == 0)
786 char *my_list[] = {"AUTHORIZATION",
787 "CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL",
790 COMPLETE_WITH_LIST(my_list);
792 /* Complete SET SESSION AUTHORIZATION with username */
793 else if (strcasecmp(prev3_wd, "SET") == 0
794 && strcasecmp(prev2_wd, "SESSION") == 0
795 && strcasecmp(prev_wd, "AUTHORIZATION") == 0)
796 COMPLETE_WITH_QUERY(Query_for_list_of_users);
797 /* Complete SET <var> with "TO" */
798 else if (strcasecmp(prev2_wd, "SET") == 0 &&
799 strcasecmp(prev4_wd, "UPDATE") != 0)
800 COMPLETE_WITH_CONST("TO");
801 /* Suggest possible variable values */
802 else if (strcasecmp(prev3_wd, "SET") == 0 &&
803 (strcasecmp(prev_wd, "TO") == 0 || strcmp(prev_wd, "=") == 0))
805 if (strcasecmp(prev2_wd, "DateStyle") == 0)
807 char *my_list[] = {"'ISO'", "'SQL'", "'Postgres'", "'European'", "'NonEuropean'", "'German'", "DEFAULT", NULL};
809 COMPLETE_WITH_LIST(my_list);
811 else if (strcasecmp(prev2_wd, "GEQO") == 0)
813 char *my_list[] = {"ON", "OFF", "DEFAULT", NULL};
815 COMPLETE_WITH_LIST(my_list);
819 char *my_list[] = {"DEFAULT", NULL};
821 COMPLETE_WITH_LIST(my_list);
826 else if (strcasecmp(prev_wd, "TRUNCATE") == 0)
827 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
830 else if (strcasecmp(prev_wd, "UNLISTEN") == 0)
831 COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_listener WHERE substr(relname,1,%d)='%s' UNION SELECT '*'::name");
834 /* If prev. word is UPDATE suggest a list of tables */
835 else if (strcasecmp(prev_wd, "UPDATE") == 0)
836 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
837 /* Complete UPDATE <table> with "SET" */
838 else if (strcasecmp(prev2_wd, "UPDATE") == 0)
839 COMPLETE_WITH_CONST("SET");
842 * If the previous word is SET (and it wasn't caught above as the
843 * _first_ word) the word before it was (hopefully) a table name and
844 * we'll now make a list of attributes.
846 else if (strcasecmp(prev_wd, "SET") == 0)
847 COMPLETE_WITH_ATTR(prev2_wd);
850 else if (strcasecmp(prev_wd, "VACUUM") == 0)
851 COMPLETE_WITH_QUERY("SELECT relname FROM pg_catalog.pg_class WHERE relkind='r' and substr(relname,1,%d)='%s' and pg_catalog.pg_table_is_visible(oid) UNION SELECT 'FULL'::name UNION SELECT 'ANALYZE'::name");
852 else if (strcasecmp(prev2_wd, "VACUUM") == 0 && (strcasecmp(prev_wd, "FULL") == 0 || strcasecmp(prev_wd, "ANALYZE") == 0))
853 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
856 /* Simple case of the word before the where being the table name */
857 else if (strcasecmp(prev_wd, "WHERE") == 0)
858 COMPLETE_WITH_ATTR(prev2_wd);
861 else if (strcasecmp(prev_wd, "FROM") == 0)
862 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
865 /* Backslash commands */
866 else if (strcmp(prev_wd, "\\connect") == 0 || strcmp(prev_wd, "\\c") == 0)
867 COMPLETE_WITH_QUERY(Query_for_list_of_databases);
868 else if (strcmp(prev_wd, "\\d") == 0)
869 COMPLETE_WITH_QUERY(Query_for_list_of_tables);
870 else if (strcmp(prev_wd, "\\h") == 0 || strcmp(prev_wd, "\\help") == 0)
871 COMPLETE_WITH_LIST(sql_commands);
872 else if (strcmp(prev_wd, "\\pset") == 0)
874 char *my_list[] = {"format", "border", "expanded", "null", "fieldsep",
875 "tuples_only", "title", "tableattr", "pager",
878 COMPLETE_WITH_LIST(my_list);
880 else if (strcmp(prev_wd, "\\cd") == 0 ||
881 strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 ||
882 strcmp(prev_wd, "\\g") == 0 ||
883 strcmp(prev_wd, "\\i") == 0 || strcmp(prev_wd, "\\include") == 0 ||
884 strcmp(prev_wd, "\\o") == 0 || strcmp(prev_wd, "\\out") == 0 ||
885 strcmp(prev_wd, "\\s") == 0 ||
886 strcmp(prev_wd, "\\w") == 0 || strcmp(prev_wd, "\\write") == 0
888 matches = completion_matches(text, filename_completion_function);
892 * Finally, we look through the list of "things", such as TABLE, INDEX
893 * and check if that was the previous word. If so, execute the query
894 * to get a list of them.
900 for (i = 0; words_after_create[i].name; i++)
901 if (strcasecmp(prev_wd, words_after_create[i].name) == 0)
903 COMPLETE_WITH_QUERY(words_after_create[i].query);
910 * If we still don't have anything to match we have to fabricate some
911 * sort of default list. If we were to just return NULL, readline
912 * automatically attempts filename completion, and that's usually no
917 COMPLETE_WITH_CONST("");
918 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
919 rl_completion_append_character = '\0';
930 /* Return our Grand List O' Matches */
936 /* GENERATOR FUNCTIONS
938 These functions do all the actual work of completing the input. They get
939 passed the text so far and the count how many times they have been called so
940 far with the same text.
941 If you read the above carefully, you'll see that these don't get called
942 directly but through the readline interface.
943 The return value is expected to be the full completion of the text, going
944 through a list each time, or NULL if there are no more matches. The string
945 will be free()'d be readline, so you must run it through strdup() or
946 something of that sort.
949 /* This one gives you one from a list of things you can put after CREATE or DROP
953 create_command_generator(char *text, int state)
955 static int list_index,
959 /* If this is the first time for this completion, init some values */
963 string_length = strlen(text);
966 /* find something that matches */
967 while ((name = words_after_create[list_index++].name))
968 if (strncasecmp(name, text, string_length) == 0)
969 return xstrdup(name);
971 /* if nothing matches, return NULL */
976 /* This creates a list of matching things, according to a query pointed to
977 by completion_charp. The query needs to have a %d and a %s in it, which will
978 be replaced by the string length of the text and the text itself. See some
979 example queries at the top.
980 The query may also have another %s in it, which will be replaced by the value
981 of completion_info_charp.
982 Ordinarily this would be used to get a list of matching tables or functions,
986 complete_from_query(char *text, int state)
988 static int list_index,
990 static PGresult *result = NULL;
991 char query_buffer[BUF_SIZE];
995 * If this ist the first time for this completion, we fetch a list of
996 * our "things" from the backend.
1001 string_length = strlen(text);
1003 /* Need to have a query */
1004 if (completion_charp == NULL)
1007 if (snprintf(query_buffer, BUF_SIZE, completion_charp, string_length, text, completion_info_charp) == -1)
1009 ERROR_QUERY_TOO_LONG;
1013 result = exec_query(query_buffer);
1016 /* Find something that matches */
1017 if (result && PQresultStatus(result) == PGRES_TUPLES_OK)
1018 while (list_index < PQntuples(result) && (item = PQgetvalue(result, list_index++, 0)))
1019 if (strncasecmp(text, item, string_length) == 0)
1020 return xstrdup(item);
1022 /* If nothing matches, free the db structure and return null */
1029 /* This function returns in order one of a fixed, NULL pointer terminated list
1030 of strings (if matching). This can be used if there are only a fixed number
1031 SQL words that can appear at certain spot.
1034 complete_from_list(char *text, int state)
1036 static int string_length,
1039 static bool casesensitive;
1042 /* need to have a list */
1043 #ifdef USE_ASSERT_CHECKING
1044 assert(completion_charpp);
1047 /* Initialization */
1051 string_length = strlen(text);
1052 casesensitive = true;
1056 while ((item = completion_charpp[list_index++]))
1058 /* First pass is case sensitive */
1059 if (casesensitive && strncmp(text, item, string_length) == 0)
1062 return xstrdup(item);
1065 /* Second pass is case insensitive, don't bother counting matches */
1066 if (!casesensitive && strncasecmp(text, item, string_length) == 0)
1067 return xstrdup(item);
1071 * No matches found. If we're not case insensitive already, lets switch
1072 * to being case insensitive and try again
1074 if (casesensitive && matches == 0)
1076 casesensitive = false;
1079 return (complete_from_list(text, state));
1082 /* If no more matches, return null. */
1087 /* This function returns one fixed string the first time even if it doesn't
1088 match what's there, and nothing the second time. This should be used if there
1089 is only one possibility that can appear at a certain spot, so misspellings
1090 will be overwritten.
1091 The string to be passed must be in completion_charp.
1094 complete_from_const(char *text, int state)
1096 (void) text; /* We don't care about what was entered
1099 #ifdef USE_ASSERT_CHECKING
1100 assert(completion_charp);
1103 return xstrdup(completion_charp);
1110 /* HELPER FUNCTIONS */
1113 /* Execute a query and report any errors. This should be the preferred way of
1114 talking to the database in this file.
1115 Note that the query passed in here must not have a semicolon at the end
1116 because we need to append LIMIT xxx.
1119 exec_query(char *query)
1122 char query_buffer[BUF_SIZE];
1124 if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK)
1126 #ifdef USE_ASSERT_CHECKING
1127 assert(query[strlen(query) - 1] != ';');
1130 if (snprintf(query_buffer, BUF_SIZE, "%s LIMIT %d;", query, completion_max_records) == -1)
1132 ERROR_QUERY_TOO_LONG;
1136 result = PQexec(pset.db, query);
1138 if (result != NULL && PQresultStatus(result) != PGRES_TUPLES_OK)
1141 psql_error("tab completion: %s failed - %s\n",
1142 query, PQresStatus(PQresultStatus(result)));
1153 /* Return the word (space delimited) before point. Set skip > 0 to skip that
1154 many words; e.g. skip=1 finds the word before the previous one.
1157 previous_word(int point, int skip)
1167 /* first we look for a space before the current word */
1168 for (i = point; i >= 0; i--)
1169 if (rl_line_buffer[i] == ' ')
1172 /* now find the first non-space which then constitutes the end */
1174 if (rl_line_buffer[i] != ' ')
1181 * If no end found we return null, because there is no word before
1188 * Otherwise we now look for the start. The start is either the
1189 * last character before any space going backwards from the end,
1190 * or it's simply character 0
1192 for (start = end; start > 0; start--)
1194 if (rl_line_buffer[start] == '"')
1195 inquotes = !inquotes;
1196 if ((rl_line_buffer[start - 1] == ' ') && inquotes == 0)
1204 s = (char *) malloc(end - start + 2);
1207 psql_error("out of memory\n");
1208 if (!pset.cur_cmd_interactive)
1214 strncpy(s, &rl_line_buffer[start], end - start + 1);
1215 s[end - start + 1] = '\0';
1225 * Surround a string with single quotes. This works for both SQL and
1226 * psql internal. Currently disable because it is reported not to
1227 * cooperate with certain versions of readline.
1230 quote_file_name(char *text, int match_type, char *quote_pointer)
1235 (void) quote_pointer; /* not used */
1237 length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2);
1240 strcpy(s + 1, text);
1241 if (match_type == SINGLE_MATCH)
1242 s[length - 2] = '\'';
1243 s[length - 1] = '\0';
1250 dequote_file_name(char *text, char quote_char)
1256 return xstrdup(text);
1258 length = strlen(text);
1259 s = malloc(length - 2 + 1);
1260 strncpy(s, text +1, length - 2);
1267 #endif /* USE_READLINE */