diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index 316a2dafbf1e..08a1df85492c 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -304,6 +304,23 @@ do { \ COMPLETE_WITH_VERSIONED_QUERY_LIST(query, list); \ } while (0) +#define COMPLETE_WITH_VERSIONED_QUERY_VERBATIM(query) \ + COMPLETE_WITH_VERSIONED_QUERY_VERBATIM_LIST(query, NULL) + +#define COMPLETE_WITH_VERSIONED_QUERY_VERBATIM_LIST(query, list) \ +do { \ + completion_vquery = query; \ + completion_charpp = list; \ + completion_verbatim = true; \ + matches = rl_completion_matches(text, complete_from_versioned_query); \ +} while (0) + +#define COMPLETE_WITH_VERSIONED_QUERY_VERBATIM_PLUS(query, ...) \ +do { \ + static const char *const list[] = { __VA_ARGS__, NULL }; \ + COMPLETE_WITH_VERSIONED_QUERY_VERBATIM_LIST(query, list); \ +} while (0) + #define COMPLETE_WITH_SCHEMA_QUERY(query) \ COMPLETE_WITH_SCHEMA_QUERY_LIST(query, NULL) @@ -1062,11 +1079,34 @@ static const SchemaQuery Query_for_trigger_of_table = { " WHERE context != 'internal' "\ " AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" +#define Query_for_list_of_alter_system_reset_vars \ +"SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings " \ +" WHERE sourcefile ~ '[\\\\/]postgresql\\.auto\\.conf$' " \ +" AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" + +static const VersionedQuery Query_for_list_of_alter_system_granted_vars[] = { + {150000, + "SELECT pg_catalog.lower(parname) FROM pg_catalog.pg_parameter_acl " + " WHERE EXISTS (SELECT FROM pg_catalog.aclexplode(paracl) " + " WHERE pg_has_role(current_role, grantee, 'usage') " + " AND privilege_type = 'ALTER SYSTEM') " + " AND pg_catalog.lower(parname) LIKE pg_catalog.lower('%s')", + }, + /* this is only used for non-superusers, who can't ALTER SYSTEM before 15, + * so no point in any fallback*/ + {0, NULL}, +}; + #define Query_for_list_of_set_vars \ "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\ " WHERE context IN ('user', 'superuser') "\ " AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" +#define Query_for_list_of_session_vars \ +"SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\ +" WHERE source = 'session' "\ +" AND pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" + #define Query_for_list_of_show_vars \ "SELECT pg_catalog.lower(name) FROM pg_catalog.pg_settings "\ " WHERE pg_catalog.lower(name) LIKE pg_catalog.lower('%s')" @@ -2458,6 +2498,10 @@ match_previous_words(int pattern_id, COMPLETE_WITH("ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT", "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT"); + else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny, "SET")) + COMPLETE_WITH("SCHEMA"); + else if (Matches("ALTER", "FOREIGN", "TABLE", MatchAny, "SET", "SCHEMA")) + COMPLETE_WITH_QUERY(Query_for_list_of_schemas); /* ALTER INDEX */ else if (Matches("ALTER", "INDEX")) @@ -2638,9 +2682,21 @@ match_previous_words(int pattern_id, /* ALTER SYSTEM SET, RESET, RESET ALL */ else if (Matches("ALTER", "SYSTEM")) COMPLETE_WITH("SET", "RESET"); - else if (Matches("ALTER", "SYSTEM", "SET|RESET")) - COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_alter_system_set_vars, - "ALL"); + else if (Matches("ALTER", "SYSTEM", "SET")) + { + if (is_superuser()) + COMPLETE_WITH_QUERY_VERBATIM(Query_for_list_of_alter_system_set_vars); + else + COMPLETE_WITH_VERSIONED_QUERY_VERBATIM(Query_for_list_of_alter_system_granted_vars); + } + else if (Matches("ALTER", "SYSTEM", "RESET")) + { + if (is_superuser()) + COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_alter_system_reset_vars, + "ALL"); + else + COMPLETE_WITH_VERSIONED_QUERY_VERBATIM(Query_for_list_of_alter_system_granted_vars); + } else if (Matches("ALTER", "SYSTEM", "SET", MatchAny)) COMPLETE_WITH("TO"); /* ALTER VIEW */ @@ -2936,9 +2992,13 @@ match_previous_words(int pattern_id, "STATISTICS", "STORAGE", /* a subset of ALTER SEQUENCE options */ "INCREMENT", "MINVALUE", "MAXVALUE", "START", "NO", "CACHE", "CYCLE"); - /* ALTER TABLE ALTER [COLUMN] SET ( */ - else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") || - Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "(")) + /* ALTER TABLE ALTER [COLUMN] RESET */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "RESET") || + Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "RESET")) + COMPLETE_WITH("("); + /* ALTER TABLE ALTER [COLUMN] SET|RESET ( */ + else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET|RESET", "(") || + Matches("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET|RESET", "(")) COMPLETE_WITH("n_distinct", "n_distinct_inherited"); /* ALTER TABLE ALTER [COLUMN] SET COMPRESSION */ else if (Matches("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "COMPRESSION") || @@ -5060,16 +5120,19 @@ match_previous_words(int pattern_id, /* SET, RESET, SHOW */ /* Complete with a variable name */ - else if (TailMatches("SET|RESET") && - !TailMatches("UPDATE", MatchAny, "SET") && - !TailMatches("ALTER", "DATABASE|USER|ROLE", MatchAny, "RESET")) + else if (TailMatches("SET") && + !TailMatches("UPDATE", MatchAny, "SET")) COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_set_vars, "CONSTRAINTS", "TRANSACTION", "SESSION", + "ROLE"); + /* Complete with variables set in the current session */ + else if (Matches("RESET")) + COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_session_vars, + "ALL", "ROLE", - "TABLESPACE", - "ALL"); + "SESSION"); else if (Matches("SHOW")) COMPLETE_WITH_QUERY_VERBATIM_PLUS(Query_for_list_of_show_vars, "SESSION AUTHORIZATION",