psql_tab_completion_for_unlogged-20110223.patch

application/octet-stream

Filename: psql_tab_completion_for_unlogged-20110223.patch
Type: application/octet-stream
Part: 0
Message: psql tab-completion for CREATE UNLOGGED TABLE

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/bin/psql/tab-complete.c 0 0
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 70aa3fa..c60ca84 100644
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
*************** typedef struct
*** 598,607 ****
  	const char *name;
  	const char *query;			/* simple query, or NULL */
  	const SchemaQuery *squery;	/* schema query, or NULL */
! 	const bool	noshow;			/* NULL or true if this word should not show
! 								 * up after CREATE or DROP */
  } pgsql_thing_t;
  
  static const pgsql_thing_t words_after_create[] = {
  	{"AGGREGATE", NULL, &Query_for_list_of_aggregates},
  	{"CAST", NULL, NULL},		/* Casts have complex structures for names, so
--- 598,610 ----
  	const char *name;
  	const char *query;			/* simple query, or NULL */
  	const SchemaQuery *squery;	/* schema query, or NULL */
! 	const bits32 flags;			/* visibility flags, see below */
  } pgsql_thing_t;
  
+ #define THING_NO_CREATE		(1 << 0)	/* should not show up after CREATE */
+ #define THING_NO_DROP		(1 << 1)	/* should not show up after DROP */
+ #define THING_NO_SHOW		(THING_NO_CREATE | THING_NO_DROP)
+ 
  static const pgsql_thing_t words_after_create[] = {
  	{"AGGREGATE", NULL, &Query_for_list_of_aggregates},
  	{"CAST", NULL, NULL},		/* Casts have complex structures for names, so
*************** static const pgsql_thing_t words_after_c
*** 612,621 ****
  	 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
  	 * to be used only by pg_dump.
  	 */
! 	{"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, true},
  	{"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
  	{"DATABASE", Query_for_list_of_databases},
! 	{"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, true},
  	{"DOMAIN", NULL, &Query_for_list_of_domains},
  	{"EXTENSION", Query_for_list_of_extensions},
  	{"FOREIGN DATA WRAPPER", NULL, NULL},
--- 615,624 ----
  	 * CREATE CONSTRAINT TRIGGER is not supported here because it is designed
  	 * to be used only by pg_dump.
  	 */
! 	{"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
  	{"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
  	{"DATABASE", Query_for_list_of_databases},
! 	{"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
  	{"DOMAIN", NULL, &Query_for_list_of_domains},
  	{"EXTENSION", Query_for_list_of_extensions},
  	{"FOREIGN DATA WRAPPER", NULL, NULL},
*************** static const pgsql_thing_t words_after_c
*** 626,632 ****
  	{"INDEX", NULL, &Query_for_list_of_indexes},
  	{"OPERATOR", NULL, NULL},	/* Querying for this is probably not such a
  								 * good idea. */
! 	{"PARSER", Query_for_list_of_ts_parsers, NULL, true},
  	{"ROLE", Query_for_list_of_roles},
  	{"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
  	{"SCHEMA", Query_for_list_of_schemas},
--- 629,636 ----
  	{"INDEX", NULL, &Query_for_list_of_indexes},
  	{"OPERATOR", NULL, NULL},	/* Querying for this is probably not such a
  								 * good idea. */
! 	{"OWNED", NULL, NULL, THING_NO_CREATE},	/* for DROP OWNED BY ... */
! 	{"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
  	{"ROLE", Query_for_list_of_roles},
  	{"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
  	{"SCHEMA", Query_for_list_of_schemas},
*************** static const pgsql_thing_t words_after_c
*** 634,649 ****
  	{"SERVER", Query_for_list_of_servers},
  	{"TABLE", NULL, &Query_for_list_of_tables},
  	{"TABLESPACE", Query_for_list_of_tablespaces},
! 	{"TEMP", NULL, NULL},		/* for CREATE TEMP TABLE ... */
! 	{"TEMPLATE", Query_for_list_of_ts_templates, NULL, true},
  	{"TEXT SEARCH", NULL, NULL},
  	{"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s'"},
  	{"TYPE", NULL, &Query_for_list_of_datatypes},
! 	{"UNIQUE", NULL, NULL},		/* for CREATE UNIQUE INDEX ... */
  	{"USER", Query_for_list_of_roles},
  	{"USER MAPPING FOR", NULL, NULL},
  	{"VIEW", NULL, &Query_for_list_of_views},
! 	{NULL, NULL, NULL, false}	/* end of list */
  };
  
  
--- 638,654 ----
  	{"SERVER", Query_for_list_of_servers},
  	{"TABLE", NULL, &Query_for_list_of_tables},
  	{"TABLESPACE", Query_for_list_of_tablespaces},
! 	{"TEMP", NULL, NULL, THING_NO_DROP},	/* for CREATE TEMP TABLE ... */
! 	{"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
  	{"TEXT SEARCH", NULL, NULL},
  	{"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s'"},
  	{"TYPE", NULL, &Query_for_list_of_datatypes},
! 	{"UNIQUE", NULL, NULL, THING_NO_DROP},	/* for CREATE UNIQUE INDEX ... */
! 	{"UNLOGGED", NULL, NULL, THING_NO_DROP},/* for CREATE UNLOGGED TABLE ... */
  	{"USER", Query_for_list_of_roles},
  	{"USER MAPPING FOR", NULL, NULL},
  	{"VIEW", NULL, &Query_for_list_of_views},
! 	{NULL}	/* end of list */
  };
  
  
*************** psql_completion(char *text, int start, i
*** 1771,1776 ****
--- 1776,1787 ----
  
  		COMPLETE_WITH_LIST(list_TEMP);
  	}
+ 	/* Complete "CREATE UNLOGGED" with TABLE */
+ 	else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
+ 			 pg_strcasecmp(prev_wd, "UNLOGGED") == 0)
+ 	{
+ 		COMPLETE_WITH_CONST("TABLE");
+ 	}
  
  /* CREATE TABLESPACE */
  	else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
*************** psql_completion(char *text, int start, i
*** 2858,2868 ****
   */
  
  /*
!  * This one gives you one from a list of things you can put after CREATE
!  * as defined above.
   */
  static char *
! create_command_generator(const char *text, int state)
  {
  	static int	list_index,
  				string_length;
--- 2869,2879 ----
   */
  
  /*
!  * Common routine for create_command_generator and drop_command_generator.
!  * Entries that have 'excluded' flags are not returned.
   */
  static char *
! create_or_drop_command_generator(const char *text, int state, bits32 excluded)
  {
  	static int	list_index,
  				string_length;
*************** create_command_generator(const char *tex
*** 2879,2885 ****
  	while ((name = words_after_create[list_index++].name))
  	{
  		if ((pg_strncasecmp(name, text, string_length) == 0) &&
! 			!words_after_create[list_index - 1].noshow)
  			return pg_strdup(name);
  	}
  	/* if nothing matches, return NULL */
--- 2890,2896 ----
  	while ((name = words_after_create[list_index++].name))
  	{
  		if ((pg_strncasecmp(name, text, string_length) == 0) &&
! 			!(words_after_create[list_index - 1].flags & excluded))
  			return pg_strdup(name);
  	}
  	/* if nothing matches, return NULL */
*************** create_command_generator(const char *tex
*** 2887,2935 ****
  }
  
  /*
   * 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) && (!words_after_create[list_index - 2].noshow))
! 			return pg_strdup(name);
! 	}
! 
! 	/* if nothing matches, return NULL */
! 	return NULL;
  }
  
  /* The following two functions are wrappers for _complete_from_query */
--- 2898,2919 ----
  }
  
  /*
+  * This one gives you one from a list of things you can put after CREATE
+  * as defined above.
+  */
+ static char *
+ create_command_generator(const char *text, int state)
+ {
+ 	return create_or_drop_command_generator(text, state, THING_NO_CREATE);
+ }
+ 
+ /*
   * This function gives you a list of things you can put after a DROP command.
   */
  static char *
  drop_command_generator(const char *text, int state)
  {
! 	return create_or_drop_command_generator(text, state, THING_NO_DROP);
  }
  
  /* The following two functions are wrappers for _complete_from_query */