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

Lines changed: 106 additions & 16 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy