aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-03-20 16:06:41 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-03-20 16:06:48 -0400
commit7fa3db367986160dee2b2b0bbfb61e1a51d486fd (patch)
treed9f44a75ce60e2c3a913392be55f4e7328cbb008 /src
parentba9a7e392171c83eb3332a757279e7088487f9a2 (diff)
downloadpostgresql-7fa3db367986160dee2b2b0bbfb61e1a51d486fd.tar.gz
postgresql-7fa3db367986160dee2b2b0bbfb61e1a51d486fd.zip
psql: handle tab completion of timezone names after "SET TIMEZONE TO".
Dagfinn Ilmari Mannsåker and Tom Lane Discussion: https://postgr.es/m/87k0curq0w.fsf@wibble.ilmari.org
Diffstat (limited to 'src')
-rw-r--r--src/bin/psql/t/010_tab_completion.pl13
-rw-r--r--src/bin/psql/tab-complete.c35
2 files changed, 48 insertions, 0 deletions
diff --git a/src/bin/psql/t/010_tab_completion.pl b/src/bin/psql/t/010_tab_completion.pl
index a54910680e5..2711935a2cc 100644
--- a/src/bin/psql/t/010_tab_completion.pl
+++ b/src/bin/psql/t/010_tab_completion.pl
@@ -338,6 +338,19 @@ check_completion(
clear_line();
+# check timezone name completion
+check_completion(
+ "SET timezone TO am\t",
+ qr|'America/|,
+ "offer partial timezone name");
+
+check_completion(
+ "new_\t",
+ qr|New_York|,
+ "complete partial timezone name");
+
+clear_line();
+
# check completion of a keyword offered in addition to object names;
# such a keyword should obey COMP_KEYWORD_CASE
foreach (
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 7b331a38ae0..183abcc2753 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -402,6 +402,24 @@ do { \
matches = rl_completion_matches(text, complete_from_schema_query); \
} while (0)
+/*
+ * Timezone completion is mostly like enum label completion, but we work
+ * a little harder since this is a more common use-case.
+ */
+#define COMPLETE_WITH_TIMEZONE_NAME() \
+do { \
+ static const char *const list[] = { "DEFAULT", NULL }; \
+ if (text[0] == '\'') \
+ completion_charp = Query_for_list_of_timezone_names_quoted_in; \
+ else if (start == 0 || rl_line_buffer[start - 1] != '\'') \
+ completion_charp = Query_for_list_of_timezone_names_quoted_out; \
+ else \
+ completion_charp = Query_for_list_of_timezone_names_unquoted; \
+ completion_charpp = list; \
+ completion_verbatim = true; \
+ matches = rl_completion_matches(text, complete_from_query); \
+} while (0)
+
#define COMPLETE_WITH_FUNCTION_ARG(function) \
do { \
set_completion_reference(function); \
@@ -1105,6 +1123,21 @@ static const SchemaQuery Query_for_trigger_of_table = {
" FROM pg_catalog.pg_cursors "\
" WHERE name LIKE '%s'"
+#define Query_for_list_of_timezone_names_unquoted \
+" SELECT name "\
+" FROM pg_catalog.pg_timezone_names() "\
+" WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
+
+#define Query_for_list_of_timezone_names_quoted_out \
+"SELECT pg_catalog.quote_literal(name) AS name "\
+" FROM pg_catalog.pg_timezone_names() "\
+" WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')"
+
+#define Query_for_list_of_timezone_names_quoted_in \
+"SELECT pg_catalog.quote_literal(name) AS name "\
+" FROM pg_catalog.pg_timezone_names() "\
+" WHERE pg_catalog.quote_literal(pg_catalog.lower(name)) LIKE pg_catalog.lower('%s')"
+
/*
* These object types were introduced later than our support cutoff of
* server version 9.2. We use the VersionedQuery infrastructure so that
@@ -4176,6 +4209,8 @@ psql_completion(const char *text, int start, int end)
" AND nspname NOT LIKE E'pg\\\\_temp%%'",
"DEFAULT");
}
+ else if (TailMatches("TimeZone", "TO|="))
+ COMPLETE_WITH_TIMEZONE_NAME();
else
{
/* generic, type based, GUC support */