mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-18 18:44:06 +08:00
psql tab completion improvements, from Greg Sabino Mullane:
* Made DELETE into "DELETE FROM" * Moved ANALZYE to the end of the list to ease EXPLAIN / VACUUM conflicts * Removed the ANALYZE xx semicolon completion: we don't do that anywhere else * Add DECLARE support * Add parens for DROP AGGREGATE * Add "CASCADE | RESTRICT" for DROP xx * Make EXPLAIN <tab> a lot smarter * GROUP "BY" and ORDER "BY" * "ISOLATION" becomes "ISOLATION LEVEL" * Fix error in which REVOKE xx ON yy was receiving "TO", now gets "FROM" * Add GRANT/REVOKE xx ON yy TO/FROM choices: usernames, GROUP, PUBLIC * PREPARE xx <tab> AS "SELECT | INSERT | UPDATE | DELETE" * Add = at end of UPDATE xx SET yy * Beef up VACUUM stuff
This commit is contained in:
parent
a9c4c9cd52
commit
4c1f9a0f0b
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.127 2005/05/07 02:22:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.128 2005/05/18 04:47:40 neilc Exp $
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
@ -368,6 +368,12 @@ static const SchemaQuery Query_for_list_of_views = {
|
||||
" FROM pg_catalog.pg_user "\
|
||||
" WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
|
||||
|
||||
#define Query_for_list_of_grant_users \
|
||||
" SELECT pg_catalog.quote_ident(usename) "\
|
||||
" FROM pg_catalog.pg_user "\
|
||||
" WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"\
|
||||
" UNION SELECT 'PUBLIC' UNION SELECT 'GROUP'"
|
||||
|
||||
/* the silly-looking length condition is just to eat up the current word */
|
||||
#define Query_for_table_owning_index \
|
||||
"SELECT pg_catalog.quote_ident(c1.relname) "\
|
||||
@ -494,7 +500,7 @@ psql_completion(char *text, int start, int end)
|
||||
|
||||
static const char *const sql_commands[] = {
|
||||
"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT",
|
||||
"COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", "DELETE", "DROP", "END", "EXECUTE",
|
||||
"COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", "DELETE FROM", "DROP", "END", "EXECUTE",
|
||||
"EXPLAIN", "FETCH", "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY",
|
||||
"PREPARE", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK", "SAVEPOINT",
|
||||
"SELECT", "SET", "SHOW", "START", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", NULL
|
||||
@ -920,14 +926,6 @@ psql_completion(char *text, int start, int end)
|
||||
pg_strcasecmp(prev_wd, "USER") == 0)
|
||||
COMPLETE_WITH_QUERY(Query_for_list_of_users);
|
||||
|
||||
/* ANALYZE */
|
||||
/* If the previous word is ANALYZE, produce list of tables. */
|
||||
else if (pg_strcasecmp(prev_wd, "ANALYZE") == 0)
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
|
||||
/* If we have ANALYZE <table>, complete with semicolon. */
|
||||
else if (pg_strcasecmp(prev2_wd, "ANALYZE") == 0)
|
||||
COMPLETE_WITH_CONST(";");
|
||||
|
||||
/* BEGIN, END, COMMIT, ABORT */
|
||||
else if (pg_strcasecmp(prev_wd, "BEGIN") == 0 ||
|
||||
pg_strcasecmp(prev_wd, "END") == 0 ||
|
||||
@ -1149,8 +1147,23 @@ psql_completion(char *text, int start, int end)
|
||||
pg_strcasecmp(prev_wd, "AS") == 0)
|
||||
COMPLETE_WITH_CONST("SELECT");
|
||||
|
||||
/* DELETE */
|
||||
/* DECLARE */
|
||||
else if (pg_strcasecmp(prev2_wd, "DECLARE") == 0)
|
||||
{
|
||||
static const char *const list_DECLARE[] =
|
||||
{"BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR", NULL};
|
||||
COMPLETE_WITH_LIST(list_DECLARE);
|
||||
}
|
||||
|
||||
else if (pg_strcasecmp(prev_wd, "CURSOR") == 0)
|
||||
{
|
||||
static const char *const list_DECLARECURSOR[] =
|
||||
{"WITH HOLD", "WITHOUT HOLD", "FOR", NULL};
|
||||
COMPLETE_WITH_LIST(list_DECLARECURSOR);
|
||||
}
|
||||
|
||||
|
||||
/* DELETE */
|
||||
/*
|
||||
* Complete DELETE with FROM (only if the word before that is not "ON"
|
||||
* (cf. rules) or "BEFORE" or "AFTER" (cf. triggers) or GRANT)
|
||||
@ -1176,16 +1189,60 @@ psql_completion(char *text, int start, int end)
|
||||
}
|
||||
/* XXX: implement tab completion for DELETE ... USING */
|
||||
|
||||
/* EXPLAIN */
|
||||
/* DROP (when not the previous word) */
|
||||
/* DROP AGGREGATE */
|
||||
else if (pg_strcasecmp(prev3_wd, "DROP") == 0 &&
|
||||
pg_strcasecmp(prev2_wd, "AGGREGATE") == 0)
|
||||
COMPLETE_WITH_CONST("(");
|
||||
|
||||
/* DROP object with CASCADE / RESTRICT */
|
||||
else if ((pg_strcasecmp(prev3_wd, "DROP") == 0 &&
|
||||
(pg_strcasecmp(prev2_wd, "CONVERSION") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "DOMAIN") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "FUNCTION") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "INDEX") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "LANGUAGE") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "SEQUENCE") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "TABLE") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "TYPE") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "VIEW") == 0)) ||
|
||||
(pg_strcasecmp(prev4_wd, "DROP") == 0 &&
|
||||
pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 &&
|
||||
prev_wd[strlen(prev_wd) - 1] == ')'))
|
||||
{
|
||||
static const char *const list_DROPCR[] =
|
||||
{"CASCADE", "RESTRICT", NULL};
|
||||
COMPLETE_WITH_LIST(list_DROPCR);
|
||||
}
|
||||
|
||||
/* EXPLAIN */
|
||||
/*
|
||||
* Complete EXPLAIN [VERBOSE] (which you'd have to type yourself) with
|
||||
* the list of SQL commands
|
||||
* Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
|
||||
*/
|
||||
else if (pg_strcasecmp(prev_wd, "EXPLAIN") == 0 ||
|
||||
(pg_strcasecmp(prev2_wd, "EXPLAIN") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "VERBOSE") == 0))
|
||||
COMPLETE_WITH_LIST(sql_commands);
|
||||
else if (pg_strcasecmp(prev_wd, "EXPLAIN") == 0)
|
||||
{
|
||||
static const char *const list_EXPLAIN[] =
|
||||
{"SELECT","INSERT","DELETE","UPDATE","DECLARE","ANALYZE","VERBOSE",NULL};
|
||||
COMPLETE_WITH_LIST(list_EXPLAIN);
|
||||
}
|
||||
else if (pg_strcasecmp(prev2_wd, "EXPLAIN") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "ANALYZE") == 0)
|
||||
{
|
||||
static const char *const list_EXPLAIN[] =
|
||||
{"SELECT","INSERT","DELETE","UPDATE","DECLARE","VERBOSE",NULL};
|
||||
COMPLETE_WITH_LIST(list_EXPLAIN);
|
||||
}
|
||||
else if (pg_strcasecmp(prev_wd, "VERBOSE") == 0 &&
|
||||
pg_strcasecmp(prev3_wd, "VACUUM") != 0 &&
|
||||
pg_strcasecmp(prev4_wd, "VACUUM") != 0 &&
|
||||
(pg_strcasecmp(prev2_wd, "ANALYZE") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "EXPLAIN") == 0))
|
||||
{
|
||||
static const char *const list_EXPLAIN[] =
|
||||
{"SELECT","INSERT","DELETE","UPDATE","DECLARE",NULL};
|
||||
COMPLETE_WITH_LIST(list_EXPLAIN);
|
||||
}
|
||||
|
||||
/* FETCH && MOVE */
|
||||
/* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
|
||||
@ -1273,15 +1330,24 @@ psql_completion(char *text, int start, int end)
|
||||
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
|
||||
else if (pg_strcasecmp(prev_wd, "TABLESPACE") == 0)
|
||||
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
|
||||
else
|
||||
else if (pg_strcasecmp(prev4_wd, "GRANT") == 0)
|
||||
COMPLETE_WITH_CONST("TO");
|
||||
else
|
||||
COMPLETE_WITH_CONST("FROM");
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: to complete with user name we need prev5_wd -- wait for a
|
||||
* more general solution there same for GRANT <sth> ON { DATABASE |
|
||||
* FUNCTION | LANGUAGE | SCHEMA | TABLESPACE } xxx TO
|
||||
*/
|
||||
/* Complete "GRANT/REVOKE * ON * TO/FROM" with username, GROUP, or PUBLIC */
|
||||
else if (pg_strcasecmp(prev3_wd, "ON") == 0 &&
|
||||
((pg_strcasecmp(prev5_wd, "GRANT") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "TO") == 0) ||
|
||||
(pg_strcasecmp(prev5_wd, "REVOKE") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "FROM") == 0)))
|
||||
COMPLETE_WITH_QUERY(Query_for_list_of_grant_users);
|
||||
|
||||
/* GROUP BY */
|
||||
else if (pg_strcasecmp(prev3_wd, "FROM") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "GROUP") == 0)
|
||||
COMPLETE_WITH_CONST("BY");
|
||||
|
||||
/* INSERT */
|
||||
/* Complete INSERT with "INTO" */
|
||||
@ -1360,10 +1426,32 @@ psql_completion(char *text, int start, int end)
|
||||
/* NOTIFY */
|
||||
else if (pg_strcasecmp(prev_wd, "NOTIFY") == 0)
|
||||
COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(relname) FROM pg_catalog.pg_listener WHERE substring(pg_catalog.quote_ident(relname),1,%d)='%s'");
|
||||
|
||||
/* OWNER TO - complete with available users*/
|
||||
else if (pg_strcasecmp(prev2_wd, "OWNER") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "TO") == 0)
|
||||
COMPLETE_WITH_QUERY(Query_for_list_of_users);
|
||||
|
||||
/* ORDER BY */
|
||||
else if (pg_strcasecmp(prev3_wd, "FROM") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "ORDER") == 0)
|
||||
COMPLETE_WITH_CONST("BY");
|
||||
else if (pg_strcasecmp(prev4_wd, "FROM") == 0 &&
|
||||
pg_strcasecmp(prev2_wd, "ORDER") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "BY") == 0)
|
||||
COMPLETE_WITH_ATTR(prev3_wd);
|
||||
|
||||
/* PREPARE xx AS */
|
||||
else if (pg_strcasecmp(prev_wd, "AS") == 0 &&
|
||||
pg_strcasecmp(prev3_wd, "PREPARE") == 0)
|
||||
{
|
||||
static const char *const list_PREPARE[] =
|
||||
{"SELECT", "UPDATE", "INSERT", "DELETE", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(list_PREPARE);
|
||||
}
|
||||
|
||||
|
||||
/* REINDEX */
|
||||
else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
|
||||
{
|
||||
@ -1407,7 +1495,7 @@ psql_completion(char *text, int start, int end)
|
||||
&& pg_strcasecmp(prev_wd, "TRANSACTION") == 0))
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
{"ISOLATION", "READ", NULL};
|
||||
{"ISOLATION LEVEL", "READ", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(my_list);
|
||||
}
|
||||
@ -1501,8 +1589,8 @@ psql_completion(char *text, int start, int end)
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
{"ISO", "SQL", "Postgres", "German",
|
||||
"YMD", "DMY", "MDY",
|
||||
"US", "European", "NonEuropean",
|
||||
"YMD", "DMY", "MDY",
|
||||
"US", "European", "NonEuropean",
|
||||
"DEFAULT", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(my_list);
|
||||
@ -1551,16 +1639,56 @@ psql_completion(char *text, int start, int end)
|
||||
else if (pg_strcasecmp(prev_wd, "SET") == 0)
|
||||
COMPLETE_WITH_ATTR(prev2_wd);
|
||||
|
||||
/* VACUUM */
|
||||
/* UPDATE xx SET yy = */
|
||||
else if (pg_strcasecmp(prev2_wd, "SET") == 0 &&
|
||||
pg_strcasecmp(prev4_wd, "UPDATE") == 0)
|
||||
COMPLETE_WITH_CONST("=");
|
||||
|
||||
/*
|
||||
* VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
|
||||
* VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
|
||||
*/
|
||||
else if (pg_strcasecmp(prev_wd, "VACUUM") == 0)
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
|
||||
" UNION SELECT 'FULL'"
|
||||
" UNION SELECT 'FREEZE'"
|
||||
" UNION SELECT 'ANALYZE'"
|
||||
" UNION SELECT 'VERBOSE'");
|
||||
else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 &&
|
||||
(pg_strcasecmp(prev_wd, "FULL") == 0 ||
|
||||
pg_strcasecmp(prev_wd, "ANALYZE") == 0 ||
|
||||
pg_strcasecmp(prev_wd, "VERBOSE") == 0))
|
||||
pg_strcasecmp(prev_wd, "FREEZE") == 0))
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
|
||||
" UNION SELECT 'ANALYZE'"
|
||||
" UNION SELECT 'VERBOSE'");
|
||||
else if (pg_strcasecmp(prev3_wd, "VACUUM") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "ANALYZE") == 0 &&
|
||||
(pg_strcasecmp(prev2_wd, "FULL") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "FREEZE") == 0))
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
|
||||
" UNION SELECT 'VERBOSE'");
|
||||
else if (pg_strcasecmp(prev3_wd, "VACUUM") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "VERBOSE") == 0 &&
|
||||
(pg_strcasecmp(prev2_wd, "FULL") == 0 ||
|
||||
pg_strcasecmp(prev2_wd, "FREEZE") == 0))
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
|
||||
" UNION SELECT 'ANALYZE'");
|
||||
else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "VERBOSE") == 0)
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
|
||||
" UNION SELECT 'ANALYZE'");
|
||||
else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 &&
|
||||
pg_strcasecmp(prev_wd, "ANALYZE") == 0)
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
|
||||
" UNION SELECT 'VERBOSE'");
|
||||
else if ((pg_strcasecmp(prev_wd, "ANALYZE") == 0 &&
|
||||
pg_strcasecmp(prev2_wd, "VERBOSE") == 0) ||
|
||||
(pg_strcasecmp(prev_wd, "VERBOSE") == 0 &&
|
||||
pg_strcasecmp(prev2_wd, "ANALYZE") == 0))
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
|
||||
|
||||
/* ANALZYE */
|
||||
/* If the previous word is ANALYZE, produce list of tables */
|
||||
else if (pg_strcasecmp(prev_wd, "ANALYZE") == 0)
|
||||
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
|
||||
|
||||
/* WHERE */
|
||||
|
Loading…
Reference in New Issue
Block a user