*
* 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 $
*/
/*----------------------------------------------------------------------
" 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) "\
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
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 ||
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)
}
/* 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 */
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" */
/* 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)
{
&& pg_strcasecmp(prev_wd, "TRANSACTION") == 0))
{
static const char *const my_list[] =
- {"ISOLATION", "READ", NULL};
+ {"ISOLATION LEVEL", "READ", NULL};
COMPLETE_WITH_LIST(my_list);
}
{
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);
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 */