psql: Generic tab completion support for enum and bool GUCs.
Author: Pavel Stehule Reviewed-By: Andres Freund Discussion: 5594FE7A.5050205@iki.fi
This commit is contained in:
parent
043113e798
commit
3ae16798f0
@ -759,6 +759,15 @@ static const SchemaQuery Query_for_list_of_matviews = {
|
||||
" (SELECT polrelid FROM pg_catalog.pg_policy "\
|
||||
" WHERE pg_catalog.quote_ident(polname)='%s')"
|
||||
|
||||
#define Query_for_enum \
|
||||
" SELECT name FROM ( "\
|
||||
" SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
|
||||
" FROM pg_catalog.pg_settings "\
|
||||
" WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
|
||||
" UNION ALL " \
|
||||
" SELECT 'DEFAULT' ) ss "\
|
||||
" WHERE pg_catalog.substring(name,1,%%d)='%%s'"
|
||||
|
||||
/*
|
||||
* This is a list of all "things" in Pgsql, which can show up after CREATE or
|
||||
* DROP; and there is also a query to get a list of them.
|
||||
@ -845,10 +854,13 @@ static char **complete_from_variables(const char *text,
|
||||
static char *complete_from_files(const char *text, int state);
|
||||
|
||||
static char *pg_strdup_keyword_case(const char *s, const char *ref);
|
||||
static char *escape_string(const char *text);
|
||||
static PGresult *exec_query(const char *query);
|
||||
|
||||
static void get_previous_words(int point, char **previous_words, int nwords);
|
||||
|
||||
static char *get_guctype(const char *varname);
|
||||
|
||||
#ifdef NOT_USED
|
||||
static char *quote_file_name(char *text, int match_type, char *quote_pointer);
|
||||
static char *dequote_file_name(char *text, char quote_char);
|
||||
@ -3684,6 +3696,7 @@ psql_completion(const char *text, int start, int end)
|
||||
else if (pg_strcasecmp(prev3_wd, "SET") == 0 &&
|
||||
(pg_strcasecmp(prev_wd, "TO") == 0 || strcmp(prev_wd, "=") == 0))
|
||||
{
|
||||
/* special cased code for individual GUCs */
|
||||
if (pg_strcasecmp(prev2_wd, "DateStyle") == 0)
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
@ -3694,20 +3707,6 @@ psql_completion(const char *text, int start, int end)
|
||||
|
||||
COMPLETE_WITH_LIST(my_list);
|
||||
}
|
||||
else if (pg_strcasecmp(prev2_wd, "IntervalStyle") == 0)
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
{"postgres", "postgres_verbose", "sql_standard", "iso_8601", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(my_list);
|
||||
}
|
||||
else if (pg_strcasecmp(prev2_wd, "GEQO") == 0)
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
{"ON", "OFF", "DEFAULT", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(my_list);
|
||||
}
|
||||
else if (pg_strcasecmp(prev2_wd, "search_path") == 0)
|
||||
{
|
||||
COMPLETE_WITH_QUERY(Query_for_list_of_schemas
|
||||
@ -3717,10 +3716,34 @@ psql_completion(const char *text, int start, int end)
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
{"DEFAULT", NULL};
|
||||
/* generic, type based, GUC support */
|
||||
|
||||
COMPLETE_WITH_LIST(my_list);
|
||||
char *guctype = get_guctype(prev2_wd);
|
||||
|
||||
if (guctype && strcmp(guctype, "enum") == 0)
|
||||
{
|
||||
char querybuf[1024];
|
||||
|
||||
snprintf(querybuf, 1024, Query_for_enum, prev2_wd);
|
||||
COMPLETE_WITH_QUERY(querybuf);
|
||||
}
|
||||
else if (guctype && strcmp(guctype, "bool") == 0)
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
{"on", "off", "true", "false", "yes", "no", "1", "0", "DEFAULT", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(my_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char *const my_list[] =
|
||||
{"DEFAULT", NULL};
|
||||
|
||||
COMPLETE_WITH_LIST(my_list);
|
||||
}
|
||||
|
||||
if (guctype)
|
||||
free(guctype);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4263,30 +4286,15 @@ _complete_from_query(int is_schema_query, const char *text, int state)
|
||||
result = NULL;
|
||||
|
||||
/* Set up suitably-escaped copies of textual inputs */
|
||||
e_text = pg_malloc(string_length * 2 + 1);
|
||||
PQescapeString(e_text, text, string_length);
|
||||
e_text = escape_string(text);
|
||||
|
||||
if (completion_info_charp)
|
||||
{
|
||||
size_t charp_len;
|
||||
|
||||
charp_len = strlen(completion_info_charp);
|
||||
e_info_charp = pg_malloc(charp_len * 2 + 1);
|
||||
PQescapeString(e_info_charp, completion_info_charp,
|
||||
charp_len);
|
||||
}
|
||||
e_info_charp = escape_string(completion_info_charp);
|
||||
else
|
||||
e_info_charp = NULL;
|
||||
|
||||
if (completion_info_charp2)
|
||||
{
|
||||
size_t charp_len;
|
||||
|
||||
charp_len = strlen(completion_info_charp2);
|
||||
e_info_charp2 = pg_malloc(charp_len * 2 + 1);
|
||||
PQescapeString(e_info_charp2, completion_info_charp2,
|
||||
charp_len);
|
||||
}
|
||||
e_info_charp2 = escape_string(completion_info_charp2);
|
||||
else
|
||||
e_info_charp2 = NULL;
|
||||
|
||||
@ -4677,6 +4685,26 @@ pg_strdup_keyword_case(const char *s, const char *ref)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* escape_string - Escape argument for use as string literal.
|
||||
*
|
||||
* The returned value has to be freed.
|
||||
*/
|
||||
static char *
|
||||
escape_string(const char *text)
|
||||
{
|
||||
size_t text_length;
|
||||
char *result;
|
||||
|
||||
text_length = strlen(text);
|
||||
|
||||
result = pg_malloc(text_length * 2 + 1);
|
||||
PQescapeStringConn(pset.db, result, text, text_length, NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Execute a query and report any errors. This should be the preferred way of
|
||||
* talking to the database in this file.
|
||||
@ -4790,6 +4818,40 @@ get_previous_words(int point, char **previous_words, int nwords)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the type for the GUC variable with the passed name.
|
||||
*
|
||||
* Returns NULL if the variable is unknown. Otherwise the returned string,
|
||||
* containing the type, has to be freed.
|
||||
*/
|
||||
static char *
|
||||
get_guctype(const char *varname)
|
||||
{
|
||||
PQExpBufferData query_buffer;
|
||||
char *e_varname;
|
||||
PGresult *result;
|
||||
char *guctype = NULL;
|
||||
|
||||
e_varname = escape_string(varname);
|
||||
|
||||
initPQExpBuffer(&query_buffer);
|
||||
appendPQExpBuffer(&query_buffer,
|
||||
"SELECT vartype FROM pg_catalog.pg_settings "
|
||||
"WHERE pg_catalog.lower(name) = pg_catalog.lower('%s')",
|
||||
e_varname);
|
||||
|
||||
result = exec_query(query_buffer.data);
|
||||
termPQExpBuffer(&query_buffer);
|
||||
free(e_varname);
|
||||
|
||||
if (PQresultStatus(result) == PGRES_TUPLES_OK && PQntuples(result) > 0)
|
||||
guctype = pg_strdup(PQgetvalue(result, 0, 0));
|
||||
|
||||
PQclear(result);
|
||||
|
||||
return guctype;
|
||||
}
|
||||
|
||||
#ifdef NOT_USED
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user