mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-04 00:02:52 -05:00 
			
		
		
		
	Add tab-completion for REASSIGN OWNED BY and DROP OWNED BY. Also fix some
whitespace issues nearby. DROP OWNED BY is actually a bit kludgy, but it seems better to do it this way rather than duplicating the words_after_create list just to add a single element.
This commit is contained in:
		
							parent
							
								
									d73336f8f4
								
							
						
					
					
						commit
						643b022bed
					
				@ -3,7 +3,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * Copyright (c) 2000-2006, PostgreSQL Global Development Group
 | 
					 * Copyright (c) 2000-2006, PostgreSQL Global Development Group
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.149 2006/03/05 15:58:52 momjian Exp $
 | 
					 * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.150 2006/04/02 09:02:41 alvherre Exp $
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*----------------------------------------------------------------------
 | 
					/*----------------------------------------------------------------------
 | 
				
			||||||
@ -465,6 +465,7 @@ static const pgsql_thing_t words_after_create[] = {
 | 
				
			|||||||
/* Forward declaration of functions */
 | 
					/* Forward declaration of functions */
 | 
				
			||||||
static char **psql_completion(char *text, int start, int end);
 | 
					static char **psql_completion(char *text, int start, int end);
 | 
				
			||||||
static char *create_command_generator(const char *text, int state);
 | 
					static char *create_command_generator(const char *text, int state);
 | 
				
			||||||
 | 
					static char *drop_command_generator(const char *text, int state);
 | 
				
			||||||
static char *complete_from_query(const char *text, int state);
 | 
					static char *complete_from_query(const char *text, int state);
 | 
				
			||||||
static char *complete_from_schema_query(const char *text, int state);
 | 
					static char *complete_from_schema_query(const char *text, int state);
 | 
				
			||||||
static char *_complete_from_query(int is_schema_query,
 | 
					static char *_complete_from_query(int is_schema_query,
 | 
				
			||||||
@ -521,11 +522,13 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
			   *prev5_wd;
 | 
								   *prev5_wd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static const char *const sql_commands[] = {
 | 
						static const char *const sql_commands[] = {
 | 
				
			||||||
		"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT",
 | 
							"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
 | 
				
			||||||
		"COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", "DELETE FROM", "DROP", "END", "EXECUTE",
 | 
							"COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
 | 
				
			||||||
		"EXPLAIN", "FETCH", "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY",
 | 
							"DELETE FROM", "DROP", "END", "EXECUTE", "EXPLAIN", "FETCH", "GRANT",
 | 
				
			||||||
		"PREPARE", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK", "SAVEPOINT",
 | 
							"INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY", "PREPARE",
 | 
				
			||||||
		"SELECT", "SET", "SHOW", "START", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", NULL
 | 
							"REASSIGN", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK",
 | 
				
			||||||
 | 
							"SAVEPOINT", "SELECT", "SET", "SHOW", "START", "TRUNCATE", "UNLISTEN",
 | 
				
			||||||
 | 
							"UPDATE", "VACUUM", NULL
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static const char *const backslash_commands[] = {
 | 
						static const char *const backslash_commands[] = {
 | 
				
			||||||
@ -536,7 +539,8 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
		"\\e", "\\echo", "\\encoding",
 | 
							"\\e", "\\echo", "\\encoding",
 | 
				
			||||||
		"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
 | 
							"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
 | 
				
			||||||
		"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
 | 
							"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
 | 
				
			||||||
		"\\o", "\\p", "\\password", "\\pset", "\\q", "\\qecho", "\\r", "\\set", "\\t", "\\T",
 | 
							"\\o", "\\p", "\\password", "\\pset", "\\q", "\\qecho", "\\r",
 | 
				
			||||||
 | 
							"\\set", "\\t", "\\T",
 | 
				
			||||||
		"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
 | 
							"\\timing", "\\unset", "\\x", "\\w", "\\z", "\\!", NULL
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -570,15 +574,19 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
	else if (!prev_wd)
 | 
						else if (!prev_wd)
 | 
				
			||||||
		COMPLETE_WITH_LIST(sql_commands);
 | 
							COMPLETE_WITH_LIST(sql_commands);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* CREATE or DROP but not ALTER (TABLE|DOMAIN|GROUP) sth DROP */
 | 
					/* CREATE */
 | 
				
			||||||
	/* complete with something you can create or drop */
 | 
						/* complete with something you can create */
 | 
				
			||||||
	else if (pg_strcasecmp(prev_wd, "CREATE") == 0 ||
 | 
						else if (pg_strcasecmp(prev_wd, "CREATE") == 0)
 | 
				
			||||||
			 (pg_strcasecmp(prev_wd, "DROP") == 0 &&
 | 
					 | 
				
			||||||
			  pg_strcasecmp(prev3_wd, "TABLE") != 0 &&
 | 
					 | 
				
			||||||
			  pg_strcasecmp(prev3_wd, "DOMAIN") != 0 &&
 | 
					 | 
				
			||||||
			  pg_strcasecmp(prev3_wd, "GROUP") != 0))
 | 
					 | 
				
			||||||
		matches = completion_matches(text, create_command_generator);
 | 
							matches = completion_matches(text, create_command_generator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* DROP, except ALTER (TABLE|DOMAIN|GROUP) sth DROP */
 | 
				
			||||||
 | 
						/* complete with something you can drop */
 | 
				
			||||||
 | 
						else if (pg_strcasecmp(prev_wd, "DROP") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev3_wd, "TABLE") != 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev3_wd, "DOMAIN") != 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev3_wd, "GROUP") != 0)
 | 
				
			||||||
 | 
							matches = completion_matches(text, drop_command_generator);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ALTER */
 | 
					/* ALTER */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@ -1248,23 +1256,22 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
			  pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 &&
 | 
								  pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 &&
 | 
				
			||||||
			  prev_wd[strlen(prev_wd) - 1] == ')'))
 | 
								  prev_wd[strlen(prev_wd) - 1] == ')'))
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		if ((pg_strcasecmp(prev3_wd, "DROP") == 0) && (pg_strcasecmp(prev2_wd, "FUNCTION") == 0))
 | 
							if ((pg_strcasecmp(prev3_wd, "DROP") == 0) && (pg_strcasecmp(prev2_wd, "FUNCTION") == 0))
 | 
				
			||||||
                {
 | 
							{
 | 
				
			||||||
                        if (find_open_parenthesis(end))
 | 
								if (find_open_parenthesis(end))
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				static const char func_args_query[] = "select pg_catalog.oidvectortypes(proargtypes)||')' from pg_proc where proname='%s'";
 | 
									static const char func_args_query[] = "select pg_catalog.oidvectortypes(proargtypes)||')' from pg_proc where proname='%s'";
 | 
				
			||||||
                        	char *tmp_buf = malloc(strlen(func_args_query) + strlen(prev_wd));
 | 
									char *tmp_buf = malloc(strlen(func_args_query) + strlen(prev_wd));
 | 
				
			||||||
                        	sprintf(tmp_buf, func_args_query, prev_wd);
 | 
									sprintf(tmp_buf, func_args_query, prev_wd);
 | 
				
			||||||
                        	COMPLETE_WITH_QUERY(tmp_buf);
 | 
									COMPLETE_WITH_QUERY(tmp_buf);
 | 
				
			||||||
                        	free(tmp_buf);
 | 
									free(tmp_buf);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
                        	COMPLETE_WITH_CONST("(");
 | 
									COMPLETE_WITH_CONST("(");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
                }
 | 
							}
 | 
				
			||||||
                else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			static const char *const list_DROPCR[] =
 | 
								static const char *const list_DROPCR[] =
 | 
				
			||||||
			{"CASCADE", "RESTRICT", NULL};
 | 
								{"CASCADE", "RESTRICT", NULL};
 | 
				
			||||||
@ -1274,7 +1281,7 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	else if (pg_strcasecmp(prev4_wd, "DROP") == 0 &&
 | 
						else if (pg_strcasecmp(prev4_wd, "DROP") == 0 &&
 | 
				
			||||||
			pg_strcasecmp(prev3_wd, "FUNCTION") == 0 &&
 | 
								pg_strcasecmp(prev3_wd, "FUNCTION") == 0 &&
 | 
				
			||||||
			pg_strcasecmp(prev_wd, "(") == 0 )
 | 
								pg_strcasecmp(prev_wd, "(") == 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		static const char func_args_query[] = "select pg_catalog.oidvectortypes(proargtypes)||')' from pg_proc where proname='%s'";
 | 
							static const char func_args_query[] = "select pg_catalog.oidvectortypes(proargtypes)||')' from pg_proc where proname='%s'";
 | 
				
			||||||
		char *tmp_buf = malloc(strlen(func_args_query) + strlen(prev2_wd));
 | 
							char *tmp_buf = malloc(strlen(func_args_query) + strlen(prev2_wd));
 | 
				
			||||||
@ -1282,6 +1289,14 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
		COMPLETE_WITH_QUERY(tmp_buf);
 | 
							COMPLETE_WITH_QUERY(tmp_buf);
 | 
				
			||||||
		free(tmp_buf);
 | 
							free(tmp_buf);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						/* DROP OWNED BY */
 | 
				
			||||||
 | 
						else if (pg_strcasecmp(prev2_wd, "DROP") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev_wd, "OWNED") == 0)
 | 
				
			||||||
 | 
							COMPLETE_WITH_CONST("BY");
 | 
				
			||||||
 | 
						else if (pg_strcasecmp(prev3_wd, "DROP") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev2_wd, "OWNED") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev_wd, "BY") == 0)
 | 
				
			||||||
 | 
							COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1502,7 +1517,7 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
	else if (pg_strcasecmp(prev_wd, "NOTIFY") == 0)
 | 
						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'");
 | 
							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 roles*/
 | 
					/* OWNER TO  - complete with available roles */
 | 
				
			||||||
	else if (pg_strcasecmp(prev2_wd, "OWNER") == 0 &&
 | 
						else if (pg_strcasecmp(prev2_wd, "OWNER") == 0 &&
 | 
				
			||||||
			 pg_strcasecmp(prev_wd, "TO") == 0)
 | 
								 pg_strcasecmp(prev_wd, "TO") == 0)
 | 
				
			||||||
		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 | 
							COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 | 
				
			||||||
@ -1526,6 +1541,25 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
		COMPLETE_WITH_LIST(list_PREPARE);
 | 
							COMPLETE_WITH_LIST(list_PREPARE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* REASSIGN OWNED BY xxx TO yyy */
 | 
				
			||||||
 | 
						else if (pg_strcasecmp(prev_wd, "REASSIGN") == 0)
 | 
				
			||||||
 | 
							COMPLETE_WITH_CONST("OWNED");
 | 
				
			||||||
 | 
						else if (pg_strcasecmp(prev_wd, "OWNED") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev2_wd, "REASSIGN") == 0)
 | 
				
			||||||
 | 
							COMPLETE_WITH_CONST("BY");
 | 
				
			||||||
 | 
						else if (pg_strcasecmp(prev_wd, "BY") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev2_wd, "OWNED") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev3_wd, "REASSIGN") == 0)
 | 
				
			||||||
 | 
							COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 | 
				
			||||||
 | 
						else if (pg_strcasecmp(prev2_wd, "BY") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev3_wd, "OWNED") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev4_wd, "REASSIGN") == 0)
 | 
				
			||||||
 | 
							COMPLETE_WITH_CONST("TO");
 | 
				
			||||||
 | 
						else if (pg_strcasecmp(prev_wd, "TO") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev3_wd, "BY") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev4_wd, "OWNED") == 0 &&
 | 
				
			||||||
 | 
								 pg_strcasecmp(prev5_wd, "REASSIGN") == 0)
 | 
				
			||||||
 | 
							COMPLETE_WITH_QUERY(Query_for_list_of_roles);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* REINDEX */
 | 
					/* REINDEX */
 | 
				
			||||||
	else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
 | 
						else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
 | 
				
			||||||
@ -1909,7 +1943,7 @@ psql_completion(char *text, int start, int end)
 | 
				
			|||||||
   something of that sort.
 | 
					   something of that sort.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This one gives you one from a list of things you can put after CREATE or DROP
 | 
					/* This one gives you one from a list of things you can put after CREATE
 | 
				
			||||||
   as defined above.
 | 
					   as defined above.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
static char *
 | 
					static char *
 | 
				
			||||||
@ -1935,6 +1969,51 @@ create_command_generator(const char *text, int state)
 | 
				
			|||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This function gives you a list of things you can put after a DROP command.
 | 
				
			||||||
 | 
					 * Very similar to create_command_generator, but has an additional entry for
 | 
				
			||||||
 | 
					 * OWNED BY.  (We do it this way in order not to duplicate the
 | 
				
			||||||
 | 
					 * words_after_create list.)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static char *
 | 
				
			||||||
 | 
					drop_command_generator(const char *text, int state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static int	list_index,
 | 
				
			||||||
 | 
									string_length;
 | 
				
			||||||
 | 
						const char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (state == 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* If this is the first time for this completion, init some values */
 | 
				
			||||||
 | 
							list_index = 0;
 | 
				
			||||||
 | 
							string_length = strlen(text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * DROP can be followed by "OWNED BY", which is not found in the list
 | 
				
			||||||
 | 
							 * for CREATE matches, so make it the first state. (We do not make it
 | 
				
			||||||
 | 
							 * the last state because it would be more difficult to detect when we
 | 
				
			||||||
 | 
							 * have to return NULL instead.)
 | 
				
			||||||
 | 
							 *
 | 
				
			||||||
 | 
							 * Make sure we advance to the next state.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							list_index++;
 | 
				
			||||||
 | 
							if (pg_strncasecmp("OWNED", text, string_length) == 0)
 | 
				
			||||||
 | 
								return pg_strdup("OWNED");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * In subsequent attempts, try to complete with the same items we use for
 | 
				
			||||||
 | 
						 * CREATE
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						while ((name = words_after_create[list_index++ - 1].name))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (pg_strncasecmp(name, text, string_length) == 0)
 | 
				
			||||||
 | 
								return pg_strdup(name);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* if nothing matches, return NULL */
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The following two functions are wrappers for _complete_from_query */
 | 
					/* The following two functions are wrappers for _complete_from_query */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user