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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy