Skip to content

Commit 2f88807

Browse files
committed
Improve tab-completion for GRANT and REVOKE.
Thomas Munro, reviewed by Michael Paquier, modified by me.
1 parent 1aba62e commit 2f88807

File tree

1 file changed

+106
-16
lines changed

1 file changed

+106
-16
lines changed

src/bin/psql/tab-complete.c

+106-16
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,9 @@ static const SchemaQuery Query_for_list_of_matviews = {
576576
" SELECT pg_catalog.quote_ident(rolname) "\
577577
" FROM pg_catalog.pg_roles "\
578578
" WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
579-
" UNION ALL SELECT 'PUBLIC'"
579+
" UNION ALL SELECT 'PUBLIC'"\
580+
" UNION ALL SELECT 'CURRENT_USER'"\
581+
" UNION ALL SELECT 'SESSION_USER'"
580582

581583
/* the silly-looking length condition is just to eat up the current word */
582584
#define Query_for_table_owning_index \
@@ -888,7 +890,7 @@ psql_completion(const char *text, int start, int end)
888890
char **matches = NULL;
889891

890892
/* This array will contain some scannage of the input line. */
891-
char *previous_words[6];
893+
char *previous_words[9];
892894

893895
/* For compactness, we use these macros to reference previous_words[]. */
894896
#define prev_wd (previous_words[0])
@@ -897,6 +899,9 @@ psql_completion(const char *text, int start, int end)
897899
#define prev4_wd (previous_words[3])
898900
#define prev5_wd (previous_words[4])
899901
#define prev6_wd (previous_words[5])
902+
#define prev7_wd (previous_words[6])
903+
#define prev8_wd (previous_words[7])
904+
#define prev9_wd (previous_words[8])
900905

901906
static const char *const sql_commands[] = {
902907
"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
@@ -3065,6 +3070,11 @@ psql_completion(const char *text, int start, int end)
30653070
pg_strcasecmp(prev_wd, "TABLE") == 0)
30663071
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
30673072

3073+
/* FOREIGN SERVER */
3074+
else if (pg_strcasecmp(prev2_wd, "FOREIGN") == 0 &&
3075+
pg_strcasecmp(prev_wd, "SERVER") == 0)
3076+
COMPLETE_WITH_QUERY(Query_for_list_of_servers);
3077+
30683078
/* GRANT && REVOKE */
30693079
/* Complete GRANT/REVOKE with a list of roles and privileges */
30703080
else if (pg_strcasecmp(prev_wd, "GRANT") == 0 ||
@@ -3118,20 +3128,23 @@ psql_completion(const char *text, int start, int end)
31183128
}
31193129

31203130
/*
3121-
* Complete GRANT/REVOKE <sth> ON with a list of tables, views, sequences,
3122-
* and indexes
3131+
* Complete GRANT/REVOKE <sth> ON with a list of tables, views, and
3132+
* sequences.
31233133
*
3124-
* keywords DATABASE, FUNCTION, LANGUAGE, SCHEMA added to query result via
3125-
* UNION; seems to work intuitively
3134+
* Keywords like DATABASE, FUNCTION, LANGUAGE and SCHEMA added to
3135+
* query result via UNION; seems to work intuitively.
31263136
*
31273137
* Note: GRANT/REVOKE can get quite complex; tab-completion as implemented
31283138
* here will only work if the privilege list contains exactly one
3129-
* privilege
3139+
* privilege.
31303140
*/
31313141
else if ((pg_strcasecmp(prev3_wd, "GRANT") == 0 ||
31323142
pg_strcasecmp(prev3_wd, "REVOKE") == 0) &&
31333143
pg_strcasecmp(prev_wd, "ON") == 0)
31343144
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
3145+
" UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
3146+
" UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
3147+
" UNION SELECT 'ALL TABLES IN SCHEMA'"
31353148
" UNION SELECT 'DATABASE'"
31363149
" UNION SELECT 'DOMAIN'"
31373150
" UNION SELECT 'FOREIGN DATA WRAPPER'"
@@ -3140,8 +3153,23 @@ psql_completion(const char *text, int start, int end)
31403153
" UNION SELECT 'LANGUAGE'"
31413154
" UNION SELECT 'LARGE OBJECT'"
31423155
" UNION SELECT 'SCHEMA'"
3156+
" UNION SELECT 'SEQUENCE'"
3157+
" UNION SELECT 'TABLE'"
31433158
" UNION SELECT 'TABLESPACE'"
31443159
" UNION SELECT 'TYPE'");
3160+
3161+
else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 ||
3162+
pg_strcasecmp(prev4_wd, "REVOKE") == 0) &&
3163+
pg_strcasecmp(prev2_wd, "ON") == 0 &&
3164+
pg_strcasecmp(prev_wd, "ALL") == 0)
3165+
{
3166+
static const char *const list_privilege_all[] =
3167+
{"FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA", "TABLES IN SCHEMA",
3168+
NULL};
3169+
3170+
COMPLETE_WITH_LIST(list_privilege_all);
3171+
}
3172+
31453173
else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 ||
31463174
pg_strcasecmp(prev4_wd, "REVOKE") == 0) &&
31473175
pg_strcasecmp(prev2_wd, "ON") == 0 &&
@@ -3153,7 +3181,12 @@ psql_completion(const char *text, int start, int end)
31533181
COMPLETE_WITH_LIST(list_privilege_foreign);
31543182
}
31553183

3156-
/* Complete "GRANT/REVOKE * ON * " with "TO/FROM" */
3184+
/*
3185+
* Complete "GRANT/REMOVE * ON DATABASE/DOMAIN/..." with a list of
3186+
* appropriate objects.
3187+
*
3188+
* Complete "GRANT/REVOKE * ON * " with "TO/FROM".
3189+
*/
31573190
else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 ||
31583191
pg_strcasecmp(prev4_wd, "REVOKE") == 0) &&
31593192
pg_strcasecmp(prev2_wd, "ON") == 0)
@@ -3168,6 +3201,10 @@ psql_completion(const char *text, int start, int end)
31683201
COMPLETE_WITH_QUERY(Query_for_list_of_languages);
31693202
else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0)
31703203
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
3204+
else if (pg_strcasecmp(prev_wd, "SEQUENCE") == 0)
3205+
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
3206+
else if (pg_strcasecmp(prev_wd, "TABLE") == 0)
3207+
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
31713208
else if (pg_strcasecmp(prev_wd, "TABLESPACE") == 0)
31723209
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
31733210
else if (pg_strcasecmp(prev_wd, "TYPE") == 0)
@@ -3178,25 +3215,78 @@ psql_completion(const char *text, int start, int end)
31783215
COMPLETE_WITH_CONST("FROM");
31793216
}
31803217

3181-
/* Complete "GRANT/REVOKE * ON * TO/FROM" with username, GROUP, or PUBLIC */
3218+
/* Complete "GRANT/REVOKE * ON * *" with TO/FROM */
31823219
else if (pg_strcasecmp(prev5_wd, "GRANT") == 0 &&
31833220
pg_strcasecmp(prev3_wd, "ON") == 0)
3221+
COMPLETE_WITH_CONST("TO");
3222+
3223+
else if (pg_strcasecmp(prev5_wd, "REVOKE") == 0 &&
3224+
pg_strcasecmp(prev3_wd, "ON") == 0)
3225+
COMPLETE_WITH_CONST("FROM");
3226+
3227+
/* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
3228+
else if ((pg_strcasecmp(prev8_wd, "GRANT") == 0 ||
3229+
pg_strcasecmp(prev8_wd, "REVOKE") == 0) &&
3230+
pg_strcasecmp(prev6_wd, "ON") == 0 &&
3231+
pg_strcasecmp(prev5_wd, "ALL") == 0 &&
3232+
pg_strcasecmp(prev3_wd, "IN") == 0 &&
3233+
pg_strcasecmp(prev2_wd, "SCHEMA") == 0)
31843234
{
3185-
if (pg_strcasecmp(prev_wd, "TO") == 0)
3186-
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
3235+
if (pg_strcasecmp(prev8_wd, "GRANT") == 0)
3236+
COMPLETE_WITH_CONST("TO");
31873237
else
3238+
COMPLETE_WITH_CONST("FROM");
3239+
}
3240+
3241+
/* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
3242+
else if ((pg_strcasecmp(prev7_wd, "GRANT") == 0 ||
3243+
pg_strcasecmp(prev7_wd, "REVOKE") == 0) &&
3244+
pg_strcasecmp(prev5_wd, "ON") == 0 &&
3245+
pg_strcasecmp(prev4_wd, "FOREIGN") == 0 &&
3246+
pg_strcasecmp(prev3_wd, "DATA") == 0 &&
3247+
pg_strcasecmp(prev2_wd, "WRAPPER") == 0)
3248+
{
3249+
if (pg_strcasecmp(prev7_wd, "GRANT") == 0)
31883250
COMPLETE_WITH_CONST("TO");
3251+
else
3252+
COMPLETE_WITH_CONST("FROM");
31893253
}
3190-
else if (pg_strcasecmp(prev5_wd, "REVOKE") == 0 &&
3191-
pg_strcasecmp(prev3_wd, "ON") == 0)
3254+
3255+
/* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
3256+
else if ((pg_strcasecmp(prev6_wd, "GRANT") == 0 ||
3257+
pg_strcasecmp(prev6_wd, "REVOKE") == 0) &&
3258+
pg_strcasecmp(prev4_wd, "ON") == 0 &&
3259+
pg_strcasecmp(prev3_wd, "FOREIGN") == 0 &&
3260+
pg_strcasecmp(prev2_wd, "SERVER") == 0)
31923261
{
3193-
if (pg_strcasecmp(prev_wd, "FROM") == 0)
3194-
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
3262+
if (pg_strcasecmp(prev6_wd, "GRANT") == 0)
3263+
COMPLETE_WITH_CONST("TO");
31953264
else
31963265
COMPLETE_WITH_CONST("FROM");
31973266
}
31983267

3199-
/* Complete "GRANT/REVOKE * TO/FROM" with username, GROUP, or PUBLIC */
3268+
/*
3269+
* Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
3270+
* CURRENT_USER, or SESSION_USER.
3271+
*/
3272+
else if (((pg_strcasecmp(prev9_wd, "GRANT") == 0 ||
3273+
pg_strcasecmp(prev8_wd, "GRANT") == 0 ||
3274+
pg_strcasecmp(prev7_wd, "GRANT") == 0 ||
3275+
pg_strcasecmp(prev6_wd, "GRANT") == 0 ||
3276+
pg_strcasecmp(prev5_wd, "GRANT") == 0) &&
3277+
pg_strcasecmp(prev_wd, "TO") == 0) ||
3278+
((pg_strcasecmp(prev9_wd, "REVOKE") == 0 ||
3279+
pg_strcasecmp(prev8_wd, "REVOKE") == 0 ||
3280+
pg_strcasecmp(prev7_wd, "REVOKE") == 0 ||
3281+
pg_strcasecmp(prev6_wd, "REVOKE") == 0 ||
3282+
pg_strcasecmp(prev5_wd, "REVOKE") == 0) &&
3283+
pg_strcasecmp(prev_wd, "FROM") == 0))
3284+
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
3285+
3286+
/*
3287+
* Complete "GRANT/REVOKE * TO/FROM" with username, PUBLIC,
3288+
* CURRENT_USER, or SESSION_USER.
3289+
*/
32003290
else if (pg_strcasecmp(prev3_wd, "GRANT") == 0 &&
32013291
pg_strcasecmp(prev_wd, "TO") == 0)
32023292
{

0 commit comments

Comments
 (0)