From 7fa3db367986160dee2b2b0bbfb61e1a51d486fd Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 20 Mar 2022 16:06:41 -0400 Subject: [PATCH] psql: handle tab completion of timezone names after "SET TIMEZONE TO". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dagfinn Ilmari Mannsåker and Tom Lane Discussion: https://postgr.es/m/87k0curq0w.fsf@wibble.ilmari.org --- src/bin/psql/t/010_tab_completion.pl | 13 +++++++++++ src/bin/psql/tab-complete.c | 35 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/bin/psql/t/010_tab_completion.pl b/src/bin/psql/t/010_tab_completion.pl index a54910680e..2711935a2c 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 7b331a38ae..183abcc275 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 */