Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4191e16

Browse files
committed
Add tab-completion for CREATE UNLOGGED TABLE in psql,
and fix unexpected completion for DROP TEMP and UNIQUE.
1 parent 2c72d70 commit 4191e16

File tree

1 file changed

+35
-51
lines changed

1 file changed

+35
-51
lines changed

src/bin/psql/tab-complete.c

Lines changed: 35 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -598,10 +598,13 @@ typedef struct
598598
const char *name;
599599
const char *query; /* simple query, or NULL */
600600
const SchemaQuery *squery; /* schema query, or NULL */
601-
const bool noshow; /* NULL or true if this word should not show
602-
* up after CREATE or DROP */
601+
const bits32 flags; /* visibility flags, see below */
603602
} pgsql_thing_t;
604603

604+
#define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */
605+
#define THING_NO_DROP (1 << 1) /* should not show up after DROP */
606+
#define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP)
607+
605608
static const pgsql_thing_t words_after_create[] = {
606609
{"AGGREGATE", NULL, &Query_for_list_of_aggregates},
607610
{"CAST", NULL, NULL}, /* Casts have complex structures for names, so
@@ -612,10 +615,10 @@ static const pgsql_thing_t words_after_create[] = {
612615
* CREATE CONSTRAINT TRIGGER is not supported here because it is designed
613616
* to be used only by pg_dump.
614617
*/
615-
{"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, true},
618+
{"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW},
616619
{"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"},
617620
{"DATABASE", Query_for_list_of_databases},
618-
{"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, true},
621+
{"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW},
619622
{"DOMAIN", NULL, &Query_for_list_of_domains},
620623
{"EXTENSION", Query_for_list_of_extensions},
621624
{"FOREIGN DATA WRAPPER", NULL, NULL},
@@ -626,24 +629,26 @@ static const pgsql_thing_t words_after_create[] = {
626629
{"INDEX", NULL, &Query_for_list_of_indexes},
627630
{"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a
628631
* good idea. */
629-
{"PARSER", Query_for_list_of_ts_parsers, NULL, true},
632+
{"OWNED", NULL, NULL, THING_NO_CREATE}, /* for DROP OWNED BY ... */
633+
{"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
630634
{"ROLE", Query_for_list_of_roles},
631635
{"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
632636
{"SCHEMA", Query_for_list_of_schemas},
633637
{"SEQUENCE", NULL, &Query_for_list_of_sequences},
634638
{"SERVER", Query_for_list_of_servers},
635639
{"TABLE", NULL, &Query_for_list_of_tables},
636640
{"TABLESPACE", Query_for_list_of_tablespaces},
637-
{"TEMP", NULL, NULL}, /* for CREATE TEMP TABLE ... */
638-
{"TEMPLATE", Query_for_list_of_ts_templates, NULL, true},
641+
{"TEMP", NULL, NULL, THING_NO_DROP}, /* for CREATE TEMP TABLE ... */
642+
{"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
639643
{"TEXT SEARCH", NULL, NULL},
640644
{"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s'"},
641645
{"TYPE", NULL, &Query_for_list_of_datatypes},
642-
{"UNIQUE", NULL, NULL}, /* for CREATE UNIQUE INDEX ... */
646+
{"UNIQUE", NULL, NULL, THING_NO_DROP}, /* for CREATE UNIQUE INDEX ... */
647+
{"UNLOGGED", NULL, NULL, THING_NO_DROP},/* for CREATE UNLOGGED TABLE ... */
643648
{"USER", Query_for_list_of_roles},
644649
{"USER MAPPING FOR", NULL, NULL},
645650
{"VIEW", NULL, &Query_for_list_of_views},
646-
{NULL, NULL, NULL, false} /* end of list */
651+
{NULL} /* end of list */
647652
};
648653

649654

@@ -1771,6 +1776,12 @@ psql_completion(char *text, int start, int end)
17711776

17721777
COMPLETE_WITH_LIST(list_TEMP);
17731778
}
1779+
/* Complete "CREATE UNLOGGED" with TABLE */
1780+
else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
1781+
pg_strcasecmp(prev_wd, "UNLOGGED") == 0)
1782+
{
1783+
COMPLETE_WITH_CONST("TABLE");
1784+
}
17741785

17751786
/* CREATE TABLESPACE */
17761787
else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
@@ -2858,11 +2869,11 @@ psql_completion(char *text, int start, int end)
28582869
*/
28592870

28602871
/*
2861-
* This one gives you one from a list of things you can put after CREATE
2862-
* as defined above.
2872+
* Common routine for create_command_generator and drop_command_generator.
2873+
* Entries that have 'excluded' flags are not returned.
28632874
*/
28642875
static char *
2865-
create_command_generator(const char *text, int state)
2876+
create_or_drop_command_generator(const char *text, int state, bits32 excluded)
28662877
{
28672878
static int list_index,
28682879
string_length;
@@ -2879,57 +2890,30 @@ create_command_generator(const char *text, int state)
28792890
while ((name = words_after_create[list_index++].name))
28802891
{
28812892
if ((pg_strncasecmp(name, text, string_length) == 0) &&
2882-
!words_after_create[list_index - 1].noshow)
2893+
!(words_after_create[list_index - 1].flags & excluded))
28832894
return pg_strdup(name);
28842895
}
28852896
/* if nothing matches, return NULL */
28862897
return NULL;
28872898
}
28882899

2900+
/*
2901+
* This one gives you one from a list of things you can put after CREATE
2902+
* as defined above.
2903+
*/
2904+
static char *
2905+
create_command_generator(const char *text, int state)
2906+
{
2907+
return create_or_drop_command_generator(text, state, THING_NO_CREATE);
2908+
}
2909+
28892910
/*
28902911
* This function gives you a list of things you can put after a DROP command.
2891-
* Very similar to create_command_generator, but has an additional entry for
2892-
* OWNED BY. (We do it this way in order not to duplicate the
2893-
* words_after_create list.)
28942912
*/
28952913
static char *
28962914
drop_command_generator(const char *text, int state)
28972915
{
2898-
static int list_index,
2899-
string_length;
2900-
const char *name;
2901-
2902-
if (state == 0)
2903-
{
2904-
/* If this is the first time for this completion, init some values */
2905-
list_index = 0;
2906-
string_length = strlen(text);
2907-
2908-
/*
2909-
* DROP can be followed by "OWNED BY", which is not found in the list
2910-
* for CREATE matches, so make it the first state. (We do not make it
2911-
* the last state because it would be more difficult to detect when we
2912-
* have to return NULL instead.)
2913-
*
2914-
* Make sure we advance to the next state.
2915-
*/
2916-
list_index++;
2917-
if (pg_strncasecmp("OWNED", text, string_length) == 0)
2918-
return pg_strdup("OWNED");
2919-
}
2920-
2921-
/*
2922-
* In subsequent attempts, try to complete with the same items we use for
2923-
* CREATE
2924-
*/
2925-
while ((name = words_after_create[list_index++ - 1].name))
2926-
{
2927-
if ((pg_strncasecmp(name, text, string_length) == 0) && (!words_after_create[list_index - 2].noshow))
2928-
return pg_strdup(name);
2929-
}
2930-
2931-
/* if nothing matches, return NULL */
2932-
return NULL;
2916+
return create_or_drop_command_generator(text, state, THING_NO_DROP);
29332917
}
29342918

29352919
/* The following two functions are wrappers for _complete_from_query */

0 commit comments

Comments
 (0)