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

Commit b48b9cb

Browse files
committed
Teach psql to do tab completion for names of psql variables.
Completion is supported in the context of \set and when interpolating a variable value using :foo etc. In passing, fix some places in tab-complete.c that weren't following project style for comment formatting. Pavel Stehule, reviewed by Itagaki Takahiro
1 parent 2ec993a commit b48b9cb

File tree

1 file changed

+134
-63
lines changed

1 file changed

+134
-63
lines changed

src/bin/psql/tab-complete.c

+134-63
Original file line numberDiff line numberDiff line change
@@ -576,20 +576,24 @@ static char *complete_from_query(const char *text, int state);
576576
static char *complete_from_schema_query(const char *text, int state);
577577
static char *_complete_from_query(int is_schema_query,
578578
const char *text, int state);
579-
static char *complete_from_const(const char *text, int state);
580579
static char *complete_from_list(const char *text, int state);
580+
static char *complete_from_const(const char *text, int state);
581+
static char **complete_from_variables(char *text,
582+
const char *prefix, const char *suffix);
581583

582584
static PGresult *exec_query(const char *query);
583585

584586
static char *previous_word(int point, int skip);
585587

586-
#if 0
588+
#ifdef NOT_USED
587589
static char *quote_file_name(char *text, int match_type, char *quote_pointer);
588590
static char *dequote_file_name(char *text, char quote_char);
589591
#endif
590592

591593

592-
/* Initialize the readline library for our purposes. */
594+
/*
595+
* Initialize the readline library for our purposes.
596+
*/
593597
void
594598
initialize_readline(void)
595599
{
@@ -607,11 +611,14 @@ initialize_readline(void)
607611
}
608612

609613

610-
/* The completion function. Acc. to readline spec this gets passed the text
611-
entered to far and its start and end in the readline buffer. The return value
612-
is some partially obscure list format that can be generated by the readline
613-
libraries completion_matches() function, so we don't have to worry about it.
614-
*/
614+
/*
615+
* The completion function.
616+
*
617+
* According to readline spec this gets passed the text entered so far and its
618+
* start and end positions in the readline buffer. The return value is some
619+
* partially obscure list format that can be generated by readline's
620+
* completion_matches() function, so we don't have to worry about it.
621+
*/
615622
static char **
616623
psql_completion(char *text, int start, int end)
617624
{
@@ -1943,7 +1950,7 @@ psql_completion(char *text, int start, int end)
19431950
pg_strcasecmp(prev_wd, "WRAPPER") == 0)
19441951
COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
19451952

1946-
/* GRANT && REVOKE*/
1953+
/* GRANT && REVOKE */
19471954
/* Complete GRANT/REVOKE with a list of privileges */
19481955
else if (pg_strcasecmp(prev_wd, "GRANT") == 0 ||
19491956
pg_strcasecmp(prev_wd, "REVOKE") == 0)
@@ -2512,7 +2519,6 @@ psql_completion(char *text, int start, int end)
25122519
pg_strcasecmp(prev3_wd, "\\copy") != 0)
25132520
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv, NULL);
25142521

2515-
25162522
/* Backslash commands */
25172523
/* TODO: \dc \dd \dl */
25182524
else if (strcmp(prev_wd, "\\connect") == 0 || strcmp(prev_wd, "\\c") == 0)
@@ -2582,6 +2588,10 @@ psql_completion(char *text, int start, int end)
25822588

25832589
COMPLETE_WITH_LIST(my_list);
25842590
}
2591+
else if (strcmp(prev_wd, "\\set") == 0)
2592+
{
2593+
matches = complete_from_variables(text, "", "");
2594+
}
25852595
else if (strcmp(prev_wd, "\\sf") == 0 || strcmp(prev_wd, "\\sf+") == 0)
25862596
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
25872597
else if (strcmp(prev_wd, "\\cd") == 0 ||
@@ -2594,6 +2604,16 @@ psql_completion(char *text, int start, int end)
25942604
)
25952605
matches = completion_matches(text, filename_completion_function);
25962606

2607+
/* Variable interpolation */
2608+
else if (text[0] == ':' && text[1] != ':')
2609+
{
2610+
if (text[1] == '\'')
2611+
matches = complete_from_variables(text, ":'", "'");
2612+
else if (text[1] == '"')
2613+
matches = complete_from_variables(text, ":\"", "\"");
2614+
else
2615+
matches = complete_from_variables(text, ":", "");
2616+
}
25972617

25982618
/*
25992619
* Finally, we look through the list of "things", such as TABLE, INDEX and
@@ -2643,23 +2663,24 @@ psql_completion(char *text, int start, int end)
26432663
}
26442664

26452665

2666+
/*
2667+
* GENERATOR FUNCTIONS
2668+
*
2669+
* These functions do all the actual work of completing the input. They get
2670+
* passed the text so far and the count how many times they have been called
2671+
* so far with the same text.
2672+
* If you read the above carefully, you'll see that these don't get called
2673+
* directly but through the readline interface.
2674+
* The return value is expected to be the full completion of the text, going
2675+
* through a list each time, or NULL if there are no more matches. The string
2676+
* will be free()'d by readline, so you must run it through strdup() or
2677+
* something of that sort.
2678+
*/
26462679

2647-
/* GENERATOR FUNCTIONS
2648-
2649-
These functions do all the actual work of completing the input. They get
2650-
passed the text so far and the count how many times they have been called so
2651-
far with the same text.
2652-
If you read the above carefully, you'll see that these don't get called
2653-
directly but through the readline interface.
2654-
The return value is expected to be the full completion of the text, going
2655-
through a list each time, or NULL if there are no more matches. The string
2656-
will be free()'d by readline, so you must run it through strdup() or
2657-
something of that sort.
2658-
*/
2659-
2660-
/* This one gives you one from a list of things you can put after CREATE
2661-
as defined above.
2662-
*/
2680+
/*
2681+
* This one gives you one from a list of things you can put after CREATE
2682+
* as defined above.
2683+
*/
26632684
static char *
26642685
create_command_generator(const char *text, int state)
26652686
{
@@ -2677,7 +2698,8 @@ create_command_generator(const char *text, int state)
26772698
/* find something that matches */
26782699
while ((name = words_after_create[list_index++].name))
26792700
{
2680-
if ((pg_strncasecmp(name, text, string_length) == 0) && !words_after_create[list_index - 1].noshow)
2701+
if ((pg_strncasecmp(name, text, string_length) == 0) &&
2702+
!words_after_create[list_index - 1].noshow)
26812703
return pg_strdup(name);
26822704
}
26832705
/* if nothing matches, return NULL */
@@ -2745,26 +2767,27 @@ complete_from_schema_query(const char *text, int state)
27452767
}
27462768

27472769

2748-
/* This creates a list of matching things, according to a query pointed to
2749-
by completion_charp.
2750-
The query can be one of two kinds:
2751-
- A simple query which must contain a %d and a %s, which will be replaced
2752-
by the string length of the text and the text itself. The query may also
2753-
have up to four more %s in it; the first two such will be replaced by the
2754-
value of completion_info_charp, the next two by the value of
2755-
completion_info_charp2.
2756-
or:
2757-
- A schema query used for completion of both schema and relation names;
2758-
these are more complex and must contain in the following order:
2759-
%d %s %d %s %d %s %s %d %s
2760-
where %d is the string length of the text and %s the text itself.
2761-
2762-
It is assumed that strings should be escaped to become SQL literals
2763-
(that is, what is in the query is actually ... '%s' ...)
2764-
2765-
See top of file for examples of both kinds of query.
2766-
*/
2767-
2770+
/*
2771+
* This creates a list of matching things, according to a query pointed to
2772+
* by completion_charp.
2773+
* The query can be one of two kinds:
2774+
*
2775+
* 1. A simple query which must contain a %d and a %s, which will be replaced
2776+
* by the string length of the text and the text itself. The query may also
2777+
* have up to four more %s in it; the first two such will be replaced by the
2778+
* value of completion_info_charp, the next two by the value of
2779+
* completion_info_charp2.
2780+
*
2781+
* 2. A schema query used for completion of both schema and relation names.
2782+
* These are more complex and must contain in the following order:
2783+
* %d %s %d %s %d %s %s %d %s
2784+
* where %d is the string length of the text and %s the text itself.
2785+
*
2786+
* It is assumed that strings should be escaped to become SQL literals
2787+
* (that is, what is in the query is actually ... '%s' ...)
2788+
*
2789+
* See top of file for examples of both kinds of query.
2790+
*/
27682791
static char *
27692792
_complete_from_query(int is_schema_query, const char *text, int state)
27702793
{
@@ -2950,10 +2973,11 @@ _complete_from_query(int is_schema_query, const char *text, int state)
29502973
}
29512974

29522975

2953-
/* This function returns in order one of a fixed, NULL pointer terminated list
2954-
of strings (if matching). This can be used if there are only a fixed number
2955-
SQL words that can appear at certain spot.
2956-
*/
2976+
/*
2977+
* This function returns in order one of a fixed, NULL pointer terminated list
2978+
* of strings (if matching). This can be used if there are only a fixed number
2979+
* SQL words that can appear at certain spot.
2980+
*/
29572981
static char *
29582982
complete_from_list(const char *text, int state)
29592983
{
@@ -3006,12 +3030,13 @@ complete_from_list(const char *text, int state)
30063030
}
30073031

30083032

3009-
/* This function returns one fixed string the first time even if it doesn't
3010-
match what's there, and nothing the second time. This should be used if there
3011-
is only one possibility that can appear at a certain spot, so misspellings
3012-
will be overwritten.
3013-
The string to be passed must be in completion_charp.
3014-
*/
3033+
/*
3034+
* This function returns one fixed string the first time even if it doesn't
3035+
* match what's there, and nothing the second time. This should be used if
3036+
* there is only one possibility that can appear at a certain spot, so
3037+
* misspellings will be overwritten. The string to be passed must be in
3038+
* completion_charp.
3039+
*/
30153040
static char *
30163041
complete_from_const(const char *text, int state)
30173042
{
@@ -3026,6 +3051,55 @@ complete_from_const(const char *text, int state)
30263051
}
30273052

30283053

3054+
/*
3055+
* This function supports completion with the name of a psql variable.
3056+
* The variable names can be prefixed and suffixed with additional text
3057+
* to support quoting usages.
3058+
*/
3059+
static char **
3060+
complete_from_variables(char *text, const char *prefix, const char *suffix)
3061+
{
3062+
char **matches;
3063+
int overhead = strlen(prefix) + strlen(suffix) + 1;
3064+
const char **varnames;
3065+
int nvars = 0;
3066+
int maxvars = 100;
3067+
int i;
3068+
struct _variable *ptr;
3069+
3070+
varnames = (const char **) pg_malloc((maxvars + 1) * sizeof(char *));
3071+
3072+
for (ptr = pset.vars->next; ptr; ptr = ptr->next)
3073+
{
3074+
char *buffer;
3075+
3076+
if (nvars >= maxvars)
3077+
{
3078+
maxvars *= 2;
3079+
varnames = (const char **) realloc(varnames,
3080+
(maxvars + 1) * sizeof(char *));
3081+
if (!varnames)
3082+
{
3083+
psql_error("out of memory\n");
3084+
exit(EXIT_FAILURE);
3085+
}
3086+
}
3087+
3088+
buffer = (char *) pg_malloc(strlen(ptr->name) + overhead);
3089+
sprintf(buffer, "%s%s%s", prefix, ptr->name, suffix);
3090+
varnames[nvars++] = buffer;
3091+
}
3092+
3093+
varnames[nvars] = NULL;
3094+
COMPLETE_WITH_LIST(varnames);
3095+
3096+
for (i = 0; i < nvars; i++)
3097+
free((void *) varnames[i]);
3098+
free(varnames);
3099+
3100+
return matches;
3101+
}
3102+
30293103

30303104
/* HELPER FUNCTIONS */
30313105

@@ -3046,7 +3120,7 @@ exec_query(const char *query)
30463120

30473121
if (PQresultStatus(result) != PGRES_TUPLES_OK)
30483122
{
3049-
#if 0
3123+
#ifdef NOT_USED
30503124
psql_error("tab completion query failed: %s\nQuery was:\n%s\n",
30513125
PQerrorMessage(pset.db), query);
30523126
#endif
@@ -3058,7 +3132,6 @@ exec_query(const char *query)
30583132
}
30593133

30603134

3061-
30623135
/*
30633136
* Return the word (space delimited) before point. Set skip > 0 to
30643137
* skip that many words; e.g. skip=1 finds the word before the
@@ -3133,7 +3206,7 @@ previous_word(int point, int skip)
31333206
return s;
31343207
}
31353208

3136-
#if 0
3209+
#ifdef NOT_USED
31373210

31383211
/*
31393212
* Surround a string with single quotes. This works for both SQL and
@@ -3158,8 +3231,6 @@ quote_file_name(char *text, int match_type, char *quote_pointer)
31583231
return s;
31593232
}
31603233

3161-
3162-
31633234
static char *
31643235
dequote_file_name(char *text, char quote_char)
31653236
{
@@ -3175,6 +3246,6 @@ dequote_file_name(char *text, char quote_char)
31753246

31763247
return s;
31773248
}
3178-
#endif /* 0 */
3249+
#endif /* NOT_USED */
31793250

31803251
#endif /* USE_READLINE */

0 commit comments

Comments
 (0)