From 4528cfd29bd7675d3c0ec426aac55857d7678085 Mon Sep 17 00:00:00 2001
From: Shi Yu <shiy.fnst@fujitsu.com>
Date: Wed, 28 Sep 2022 17:59:17 +0800
Subject: [PATCH v4] Fix tab completion for GRANT/REVOKE

The result of tab completion for GRANT contains GRANT, but there's no such a
privilege. Fix it in this patch. Also add tab completion for
GRANT/REVOKE ALL PRIVILEGES.
---
 src/bin/psql/tab-complete.c | 70 +++++++++++++++++++++++++++++--------
 1 file changed, 55 insertions(+), 15 deletions(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 584d9d5ae6..ac5ee56182 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3749,9 +3749,29 @@ psql_completion(const char *text, int start, int end)
 			COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
 						  "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
 						  "EXECUTE", "USAGE", "ALL");
-		else
+		else if (TailMatches("REVOKE", "GRANT"))
+			COMPLETE_WITH("OPTION FOR");
+		else if (TailMatches("GRANT") ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR"))
 			COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
-									 "GRANT",
+									 "SELECT",
+									 "INSERT",
+									 "UPDATE",
+									 "DELETE",
+									 "TRUNCATE",
+									 "REFERENCES",
+									 "TRIGGER",
+									 "CREATE",
+									 "CONNECT",
+									 "TEMPORARY",
+									 "EXECUTE",
+									 "USAGE",
+									 "SET",
+									 "ALTER SYSTEM",
+									 "ALL");
+		else if (TailMatches("REVOKE"))
+			COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
+									 "GRANT OPTION FOR",
 									 "SELECT",
 									 "INSERT",
 									 "UPDATE",
@@ -3769,8 +3789,6 @@ psql_completion(const char *text, int start, int end)
 									 "ALL");
 	}
 
-	else if (TailMatches("REVOKE", "GRANT"))
-		COMPLETE_WITH("OPTION FOR");
 	else if (TailMatches("REVOKE", "GRANT", "OPTION"))
 		COMPLETE_WITH("FOR");
 
@@ -3807,13 +3825,18 @@ psql_completion(const char *text, int start, int end)
 	else if (TailMatches("GRANT|REVOKE", MatchAny) ||
 			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny))
 	{
-		if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
+		if (TailMatches("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE"))
 			COMPLETE_WITH("ON");
+		else if (TailMatches("ALL"))
+			COMPLETE_WITH("ON", "PRIVILEGES");
 		else if (TailMatches("GRANT", MatchAny))
 			COMPLETE_WITH("TO");
 		else
 			COMPLETE_WITH("FROM");
 	}
+	else if (TailMatches("GRANT|REVOKE", "ALL", "PRIVILEGES") ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALL", "PRIVILEGES"))
+		COMPLETE_WITH("ON");
 
 	/*
 	 * Complete GRANT/REVOKE <sth> ON with a list of appropriate relations.
@@ -3823,7 +3846,9 @@ psql_completion(const char *text, int start, int end)
 	 * privilege.
 	 */
 	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON") ||
-			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON"))
+			 TailMatches("GRANT|REVOKE", "ALL", "PRIVILEGES", "ON") ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON") ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALL", "PRIVILEGES", "ON") )
 	{
 		/*
 		 * With ALTER DEFAULT PRIVILEGES, restrict completion to the kinds of
@@ -3855,14 +3880,18 @@ psql_completion(const char *text, int start, int end)
 											"TYPE");
 	}
 	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL") ||
-			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL"))
+			 TailMatches("GRANT|REVOKE", "ALL", "PRIVILEGES", "ON", "ALL") ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL") ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALL", "PRIVILEGES", "ON", "ALL"))
 		COMPLETE_WITH("FUNCTIONS IN SCHEMA",
 					  "PROCEDURES IN SCHEMA",
 					  "ROUTINES IN SCHEMA",
 					  "SEQUENCES IN SCHEMA",
 					  "TABLES IN SCHEMA");
 	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN") ||
-			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN"))
+			 TailMatches("GRANT|REVOKE", "ALL", "PRIVILEGES", "ON", "FOREIGN") ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN") ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALL", "PRIVILEGES", "ON", "FOREIGN"))
 		COMPLETE_WITH("DATA WRAPPER", "SERVER");
 
 	/*
@@ -3872,7 +3901,9 @@ psql_completion(const char *text, int start, int end)
 	 * Complete "GRANT/REVOKE * ON *" with "TO/FROM".
 	 */
 	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", MatchAny) ||
-			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny))
+			 TailMatches("GRANT|REVOKE", "ALL", "PRIVILEGES", "ON", MatchAny) ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", MatchAny) ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALL", "PRIVILEGES", "ON", MatchAny))
 	{
 		if (TailMatches("DATABASE"))
 			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
@@ -3938,9 +3969,12 @@ psql_completion(const char *text, int start, int end)
 
 	/* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
 	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
-			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
+			 TailMatches("GRANT|REVOKE", "ALL", "PRIVILEGES", "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "ALL", "ALL", "PRIVILEGES", "IN", "SCHEMA", MatchAny))
 	{
-		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
+		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) ||
+			TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
 			COMPLETE_WITH("TO");
 		else
 			COMPLETE_WITH("FROM");
@@ -3948,9 +3982,12 @@ psql_completion(const char *text, int start, int end)
 
 	/* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
 	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
-			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
+			 TailMatches("GRANT|REVOKE", "ALL", "PRIVILEGES", "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALL", "PRIVILEGES", "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
 	{
-		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
+		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) ||
+			TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
 			COMPLETE_WITH("TO");
 		else
 			COMPLETE_WITH("FROM");
@@ -3958,9 +3995,12 @@ psql_completion(const char *text, int start, int end)
 
 	/* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
 	else if (TailMatches("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
-			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
+			 TailMatches("GRANT|REVOKE", "ALL", "PRIVILEGES", "ON", "FOREIGN", "SERVER", MatchAny) ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny) ||
+			 TailMatches("REVOKE", "GRANT", "OPTION", "FOR", "ALL", "PRIVILEGES", "ON", "FOREIGN", "SERVER", MatchAny))
 	{
-		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
+		if (TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) ||
+			TailMatches("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
 			COMPLETE_WITH("TO");
 		else
 			COMPLETE_WITH("FROM");
-- 
2.31.1

