-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
 
 
Attached are some tab-completion enhancements for psql. In rough order,
they are:
 
* 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
 
- --
Greg Sabino Mullane [EMAIL PROTECTED]
PGP Key: 0x14964AC8 200505161845
http://biglumber.com/x/web?pk=2529DF6AB8F79407E94445B4BC9B906714964AC8
-----BEGIN PGP SIGNATURE-----
 
iD8DBQFCiSKGvJuQZxSWSsgRAu72AKCpp9kOoXGt3+4Krew77ShzPhMaiQCdEU08
XYkiOCkrDdYILwEO3QQlLUk=
=NmML
-----END PGP SIGNATURE-----

Index: tab-complete.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v
retrieving revision 1.127
diff -c -r1.127 tab-complete.c
*** tab-complete.c	7 May 2005 02:22:49 -0000	1.127
--- tab-complete.c	16 May 2005 19:59:28 -0000
***************
*** 368,373 ****
--- 368,379 ----
  "   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,500 ****
  
  	static const char *const sql_commands[] = {
  		"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT",
! 		"COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", "DELETE", "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
--- 500,506 ----
  
  	static const char *const sql_commands[] = {
  		"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT",
! 		"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,932 ****
  			 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 ||
--- 926,932 ----
  			 pg_strcasecmp(prev_wd, "USER") == 0)
  		COMPLETE_WITH_QUERY(Query_for_list_of_users);
  
! /* ANALYZE  - moved to end to ease EXPLAIN / VACUUM conflicts */
  
  /* BEGIN, END, COMMIT, ABORT */
  	else if (pg_strcasecmp(prev_wd, "BEGIN") == 0 ||
***************
*** 1149,1154 ****
--- 1149,1171 ----
  			 pg_strcasecmp(prev_wd, "AS") == 0)
  		COMPLETE_WITH_CONST("SELECT");
  
+ /* 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 */
  
  	/*
***************
*** 1176,1191 ****
  	}
  	/* XXX: implement tab completion for DELETE ... USING */
  
  /* EXPLAIN */
  
  	/*
! 	 * Complete EXPLAIN [VERBOSE] (which you'd have to type yourself) with
! 	 * the list of SQL 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);
  
  /* FETCH && MOVE */
  	/* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
--- 1193,1259 ----
  	}
  	/* XXX: implement tab completion for DELETE ... USING */
  
+ /* 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 [ANALYZE] [VERBOSE] with list of EXPLAIN-able 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,1287 ****
  			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
! 			COMPLETE_WITH_CONST("TO");
  	}
  
! 	/*
! 	 * 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
! 	 */
  
  /* INSERT */
  	/* Complete INSERT with "INTO" */
--- 1341,1364 ----
  			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 if (pg_strcasecmp(prev4_wd, "GRANT") == 0)
+ 				COMPLETE_WITH_CONST("TO");
  		else
! 				COMPLETE_WITH_CONST("FROM");
  	}
  
! 	/* 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,1369 ****
--- 1437,1469 ----
  /* 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,1413 ****
  				 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0))
  	{
  		static const char *const my_list[] =
! 		{"ISOLATION", "READ", NULL};
  
  		COMPLETE_WITH_LIST(my_list);
  	}
--- 1507,1513 ----
  				 && pg_strcasecmp(prev_wd, "TRANSACTION") == 0))
  	{
  		static const char *const my_list[] =
! 		{"ISOLATION LEVEL", "READ", NULL};
  
  		COMPLETE_WITH_LIST(my_list);
  	}
***************
*** 1551,1567 ****
  	else if (pg_strcasecmp(prev_wd, "SET") == 0)
  		COMPLETE_WITH_ATTR(prev2_wd);
  
  /* VACUUM */
  	else if (pg_strcasecmp(prev_wd, "VACUUM") == 0)
  		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
  								   " UNION SELECT 'FULL'"
  								   " 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))
! 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
  
  /* WHERE */
  	/* Simple case of the word before the where being the table name */
--- 1651,1710 ----
  	else if (pg_strcasecmp(prev_wd, "SET") == 0)
  		COMPLETE_WITH_ATTR(prev2_wd);
  
+ /* 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 [, ...] ) ] ]
+ */
+ 
+ 
  /* VACUUM */
  	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, "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 */
  	/* Simple case of the word before the where being the table name */
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to