aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bin/psql/t/010_tab_completion.pl24
-rw-r--r--src/bin/psql/tab-complete.c63
2 files changed, 56 insertions, 31 deletions
diff --git a/src/bin/psql/t/010_tab_completion.pl b/src/bin/psql/t/010_tab_completion.pl
index 569dd442e8a..005961f34d4 100644
--- a/src/bin/psql/t/010_tab_completion.pl
+++ b/src/bin/psql/t/010_tab_completion.pl
@@ -339,8 +339,7 @@ check_completion(
clear_line();
# check completion of a keyword offered in addition to object names;
-# such a keyword should obey COMP_KEYWORD_CASE once only keyword
-# completions are possible
+# such a keyword should obey COMP_KEYWORD_CASE
foreach (
[ 'lower', 'CO', 'column' ],
[ 'upper', 'co', 'COLUMN' ],
@@ -353,10 +352,6 @@ foreach (
"\\set COMP_KEYWORD_CASE $case\n",
qr/postgres=#/,
"set completion case to '$case'");
- check_completion("alter table tab1 rename c\t\t",
- qr|COLUMN|,
- "offer keyword COLUMN for input c<TAB>, COMP_KEYWORD_CASE = $case");
- clear_query();
check_completion("alter table tab1 rename $in\t\t\t",
qr|$out|,
"offer keyword $out for input $in<TAB>, COMP_KEYWORD_CASE = $case");
@@ -410,6 +405,23 @@ check_completion(" iso\t", qr/iso_8601 /, "complete a GUC enum value");
clear_query();
+# same, for qualified GUC names
+check_completion(
+ "DO \$\$begin end\$\$ LANGUAGE plpgsql;\n",
+ qr/postgres=# /,
+ "load plpgsql extension");
+
+check_completion("set plpg\t", qr/plpg\a?sql\./,
+ "complete prefix of a GUC name");
+check_completion(
+ "var\t\t",
+ qr/variable_conflict TO/,
+ "complete a qualified GUC name");
+check_completion(" USE_C\t",
+ qr/use_column/, "complete a qualified GUC enum value");
+
+clear_query();
+
# check completions for psql variables
check_completion("\\set VERB\t", qr/VERBOSITY /,
"complete a psql variable name");
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index d1e421bc0f1..25d3abbcf18 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -257,13 +257,22 @@ do { \
} while (0)
#define COMPLETE_WITH_QUERY_VERBATIM(query) \
+ COMPLETE_WITH_QUERY_VERBATIM_LIST(query, NULL)
+
+#define COMPLETE_WITH_QUERY_VERBATIM_LIST(query, list) \
do { \
completion_charp = query; \
- completion_charpp = NULL; \
+ completion_charpp = list; \
completion_verbatim = true; \
matches = rl_completion_matches(text, complete_from_query); \
} while (0)
+#define COMPLETE_WITH_QUERY_VERBATIM_PLUS(query, ...) \
+do { \
+ static const char *const list[] = { __VA_ARGS__, NULL }; \
+ COMPLETE_WITH_QUERY_VERBATIM_LIST(query, list); \
+} while (0)
+
#define COMPLETE_WITH_VERSIONED_QUERY(query) \
COMPLETE_WITH_VERSIONED_QUERY_LIST(query, NULL)
@@ -1273,6 +1282,7 @@ static char *_complete_from_query(const char *simple_query,
bool verbatim,
const char *text, int state);
static void set_completion_reference(const char *word);
+static void set_completion_reference_verbatim(const char *word);
static char *complete_from_list(const char *text, int state);
static char *complete_from_const(const char *text, int state);
static void append_variable_names(char ***varnames, int *nvars,
@@ -2058,8 +2068,8 @@ psql_completion(const char *text, int start, int end)
else if (Matches("ALTER", "SYSTEM"))
COMPLETE_WITH("SET", "RESET");
else if (Matches("ALTER", "SYSTEM", "SET|RESET"))
- COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_alter_system_set_vars,
- "ALL");
+ COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_alter_system_set_vars,
+ "ALL");
else if (Matches("ALTER", "SYSTEM", "SET", MatchAny))
COMPLETE_WITH("TO");
/* ALTER VIEW <name> */
@@ -4038,17 +4048,17 @@ psql_completion(const char *text, int start, int end)
/* SET, RESET, SHOW */
/* Complete with a variable name */
else if (TailMatches("SET|RESET") && !TailMatches("UPDATE", MatchAny, "SET"))
- COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_set_vars,
- "CONSTRAINTS",
- "TRANSACTION",
- "SESSION",
- "ROLE",
- "TABLESPACE",
- "ALL");
+ COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars,
+ "CONSTRAINTS",
+ "TRANSACTION",
+ "SESSION",
+ "ROLE",
+ "TABLESPACE",
+ "ALL");
else if (Matches("SHOW"))
- COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_show_vars,
- "SESSION AUTHORIZATION",
- "ALL");
+ COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_show_vars,
+ "SESSION AUTHORIZATION",
+ "ALL");
else if (Matches("SHOW", "SESSION"))
COMPLETE_WITH("AUTHORIZATION");
/* Complete "SET TRANSACTION" */
@@ -4150,7 +4160,7 @@ psql_completion(const char *text, int start, int end)
{
if (strcmp(guctype, "enum") == 0)
{
- set_completion_reference(prev2_wd);
+ set_completion_reference_verbatim(prev2_wd);
COMPLETE_WITH_QUERY_PLUS(Query_for_values_of_enum_GUC,
"DEFAULT");
}
@@ -4707,7 +4717,7 @@ complete_from_versioned_schema_query(const char *text, int state)
* version of the string provided in completion_ref_object. If there is a
* third '%s', it will be replaced by a suitably-escaped version of the string
* provided in completion_ref_schema. Those strings should be set up
- * by calling set_completion_reference().
+ * by calling set_completion_reference or set_completion_reference_verbatim.
* Simple queries should return a single column of matches. If "verbatim"
* is true, the matches are returned as-is; otherwise, they are taken to
* be SQL identifiers and quoted if necessary.
@@ -5037,11 +5047,7 @@ _complete_from_query(const char *simple_query,
if (pg_strncasecmp(text, item, strlen(text)) == 0)
{
num_keywords++;
- /* Match keyword case if we are returning only keywords */
- if (num_schema_only == 0 && num_query_other == 0)
- return pg_strdup_keyword_case(item, text);
- else
- return pg_strdup(item);
+ return pg_strdup_keyword_case(item, text);
}
}
}
@@ -5059,11 +5065,7 @@ _complete_from_query(const char *simple_query,
if (pg_strncasecmp(text, item, strlen(text)) == 0)
{
num_keywords++;
- /* Match keyword case if we are returning only keywords */
- if (num_schema_only == 0 && num_query_other == 0)
- return pg_strdup_keyword_case(item, text);
- else
- return pg_strdup(item);
+ return pg_strdup_keyword_case(item, text);
}
}
}
@@ -5100,6 +5102,17 @@ set_completion_reference(const char *word)
&schemaquoted, &objectquoted);
}
+/*
+ * Set up completion_ref_object when it should just be
+ * the given word verbatim.
+ */
+static void
+set_completion_reference_verbatim(const char *word)
+{
+ completion_ref_schema = NULL;
+ completion_ref_object = pg_strdup(word);
+}
+
/*
* This function returns in order one of a fixed, NULL pointer terminated list