From 427bd0b2793350122d8ba203cdcdbafe0c31a2df Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Mon, 26 Dec 2016 17:00:23 +0900
Subject: [PATCH 17/17] Add suggestions of IF (NOT) EXISTS

Add suggestions of IF EXISTS and IF NOT EXISTS to all applicable
existing completions. This changes several existing behaviors related
USER MAPPING, PROCEDUAL LANGUAGE.
---
 src/bin/psql/tab-complete.c | 229 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 183 insertions(+), 46 deletions(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index b69e278..6147cc1 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -743,7 +743,8 @@ static const pgsql_thing_t words_after_create[] = {
 								 * good idea. */
 	{"OWNED", NULL, NULL, THING_NO_CREATE},		/* for DROP OWNED BY ... */
 	{"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
-	{"POLICY", NULL, NULL},
+	{"POLICY", Query_for_list_of_policies, NULL},
+	{"PROCEDUAL LANGUAGE", NULL, NULL},
 	{"ROLE", Query_for_list_of_roles},
 	{"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
 	{"SCHEMA", Query_for_list_of_schemas},
@@ -760,7 +761,7 @@ static const pgsql_thing_t words_after_create[] = {
 	{"UNLOGGED", NULL, NULL, THING_NO_DROP},	/* for CREATE UNLOGGED TABLE
 												 * ... */
 	{"USER", Query_for_list_of_roles},
-	{"USER MAPPING FOR", NULL, NULL},
+	{"USER MAPPING", NULL, NULL},
 	{"VIEW", NULL, &Query_for_list_of_views},
 	{NULL}						/* end of list */
 };
@@ -1114,7 +1115,9 @@ psql_completion_internal(const char *text, char **previous_words,
 	/* ALTER TABLE */
 	if (Matches2("ALTER", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
-									  ADDLIST1("ALL IN TABLESPACE"));
+							  ADDLIST2("ALL IN TABLESPACE","IF EXISTS"));
+	/* Remove IF EXISTS */
+	HeadMatchAndRemove4(3, 2, "ALTER", "TABLE", "IF", "EXISTS");
 
 	/* ALTER something */
 	if (Matches1("ALTER"))
@@ -1218,6 +1221,13 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
 		COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
 
+	/* ALTER FOREIGN TABLE  */
+	if (Matches3("ALTER", "FOREIGN", "TABLE"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_foreign_tables,
+									  ADDLIST1("IF EXISTS"));
+	/* Remove IF EXISTS  */
+	HeadMatchAndRemove5(4, 2, "ALTER", "FOREIGN", "TABLE", "IF", "EXISTS");
+
 	/* ALTER FOREIGN TABLE <name> */
 	if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
 	{
@@ -1232,7 +1242,10 @@ psql_completion_internal(const char *text, char **previous_words,
 	/* ALTER INDEX */
 	if (Matches2("ALTER", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
-									  ADDLIST1("ALL IN TABLESPACE"));
+						  ADDLIST2("ALL IN TABLESPACE", "IF EXISTS"));
+	/* Remove IF EXISTS */
+	HeadMatchAndRemove4(3, 2, "ALTER", "INDEX", "IF", "EXISTS");
+
 	/* ALTER INDEX <name> */
 	if (Matches3("ALTER", "INDEX", MatchAny))
 		COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
@@ -1261,7 +1274,10 @@ psql_completion_internal(const char *text, char **previous_words,
 	/* ALTER MATERIALIZED VIEW */
 	if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews,
-									  ADDLIST1("ALL IN TABLESPACE"));
+						  ADDLIST2("ALL IN TABLESPACE", "IF EXISTS"));
+	/* Remove IF EXISTS */
+	HeadMatchAndRemove5(4, 2, "ALTER", "MATERIALIZED", "VIEW", "IF", "EXISTS");
+
 
 	/* ALTER USER,ROLE <name> */
 	if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
@@ -1366,14 +1382,21 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
 		COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
 	/* ALTER SEQUENCE <name> */
+	if (Matches2("ALTER", "SEQUENCE"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_sequences,
+									  ADDLIST1("IF EXISTS"));
+	/* Remove IF EXISTS */
+	HeadMatchAndRemove4(3, 2, "ALTER", "SEQUENCE", "IF", "EXISTS");
 	if (Matches3("ALTER", "SEQUENCE", MatchAny))
 	{
 		static const char *const list_ALTERSEQUENCE[] =
 		{"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
-		"SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL};
+		 "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", "IF EXISTS", NULL};
 
 		COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
 	}
+	/* Remove IF EXISTS */
+	HeadMatchAndRemove4(3, 2, "ALTER", "SEQUENCE", "IF", "EXISTS");
 	/* ALTER SEQUENCE <name> NO */
 	if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
 		COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
@@ -1390,6 +1413,12 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
 	/* ALTER VIEW <name> */
+	if (Matches2("ALTER", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views,
+									  ADDLIST1("IF EXISTS"));
+	/* Remove IF EXISTS */
+	HeadMatchAndRemove4(3, 2, "ALTER", "VIEW", "IF", "EXISTS");
+
 	if (Matches3("ALTER", "VIEW", MatchAny))
 		COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
 							"SET SCHEMA");
@@ -1534,12 +1563,26 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
 		COMPLETE_WITH_CONST("TO");
 
-	/* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
+	/*
+	 * If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT and IF
+	 * EXISTS
+	 */
 	if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
-		COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
+		COMPLETE_WITH_LIST3("COLUMN", "CONSTRAINT", "IF EXISTS");
 	/* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
-	if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
-		COMPLETE_WITH_ATTR(prev3_wd);
+	if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN|CONSTRAINT"))
+		COMPLETE_WITH_ATTR_KW(prev3_wd, ADDLIST1("IF EXISTS"));
+	/* Remove IF EXISTS and COLUMN*/
+	HeadMatchAndRemove7(6, 2,
+						"ALTER", "TABLE", MatchAny, "DROP", "COLUMN|CONSTRAINT",
+						"IF", "EXISTS");
+	HeadMatchAndRemove6(5, 2,
+						"ALTER", "TABLE", MatchAny, "DROP", "IF", "EXISTS");
+	HeadMatchAndRemove5(5, 1,
+						"ALTER", "TABLE", MatchAny, "DROP", "COLUMN");
+	/* This doesn't match DROP CONSTRAINT */
+	if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
+		COMPLETE_WITH_ATTR(prev2_wd);
 
 	/*
 	 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
@@ -1686,6 +1729,12 @@ psql_completion_internal(const char *text, char **previous_words,
 	 * If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
 	 * of attributes
 	 */
+	/* DROP can have IF EXISTS */
+	if (Matches5("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE"))
+		COMPLETE_WITH_ATTR_KW(prev3_wd, ADDLIST1("IF EXISTS"));
+	/* Remove IF EXISTS */
+	HeadMatchAndRemove7(6, 2, "ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE",
+						"IF", "EXISTS");
 	if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
 		COMPLETE_WITH_ATTR(prev3_wd);
 	/* ALTER TYPE ALTER ATTRIBUTE <foo> */
@@ -1844,7 +1893,14 @@ psql_completion_internal(const char *text, char **previous_words,
 	/* CREATE EXTENSION */
 	/* Complete with available extensions rather than installed ones. */
 	if (Matches2("CREATE", "EXTENSION"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_available_extensions,
+							   ADDLIST1("IF NOT EXISTS"));
+	/* Remove IF NOT EXISTS */
+	HeadMatchAndRemove5(3, 3, "CREATE", "EXTENSION", "IF", "NOT", "EXISTS");
+	/* Complete with available extensions rather than installed ones. */
+	if (Matches2("CREATE", "EXTENSION"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
+
 	/* CREATE EXTENSION <name> */
 	if (Matches3("CREATE", "EXTENSION", MatchAny))
 		COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
@@ -1859,7 +1915,7 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches2("CREATE", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
 
-	/* CREATE FOREIGN DATA WRAPPER */
+	/* CREATE FOREIGN DATA WRAPPER - doesn't accept IF NOT EXISTS */
 	if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
 		COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
 
@@ -1875,7 +1931,7 @@ psql_completion_internal(const char *text, char **previous_words,
 	 */
 	if (Matches2("CREATE", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
-									  ADDLIST2("ON", "CONCURRENTLY"));
+						  ADDLIST3("ON", "CONCURRENTLY", "IF NOT EXISTS"));
 	/* Remove CONCURRENTLY for further completion */
 	HeadMatchAndRemove3(3, 1, "CREATE", "INDEX", "CONCURRENTLY");
 
@@ -1885,7 +1941,13 @@ psql_completion_internal(const char *text, char **previous_words,
 	 */
 	if (Matches2("CREATE", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
-									  ADDLIST1("ON"));
+									  ADDLIST2("ON", "IF NOT EXISTS"));
+	/* IF NOT EXISTS must be followed by a table name */
+	if (Matches5("CREATE", "INDEX", "IF", "NOT", "EXISTS"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
+	/* Remove IF NOT EXISTS */
+	HeadMatchAndRemove6(3, 3,
+						"CREATE", "INDEX", "IF", "NOT", "EXISTS", MatchAny);
 
 	/* Complete CREATE [UNIQUE] INDEX [CONCURRENTLY] <sth> with "ON" */
 	if (Matches3("CREATE", "INDEX", MatchAny))
@@ -2018,8 +2080,21 @@ psql_completion_internal(const char *text, char **previous_words,
 		}
 	}
 
+/* CREATE SCHEMA */
+	if (Matches2("CREATE", "SCHEMA"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_schemas,
+							   ADDLIST1("IF NOT EXISTS"));
+	/* Remove IF NOT EXISTS */
+	HeadMatchAndRemove5(3, 3, "CREATE", "SCHEMA", "IF", "NOT", "EXISTS");
+
 /* CREATE SEQUENCE */
 	HeadMatchAndRemove3(2, 1, "CREATE", "TEMP|TEMPORARY", "SEQUENCE");
+	if (Matches2("CREATE", "SEQUENCE"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_sequences,
+									  ADDLIST1("IF NOT EXISTS"));
+	/* Remove IF NOT EXISTS */
+	HeadMatchAndRemove5(3, 3, "CREATE", "SEQUENCE", "IF", "NOT", "EXISTS");
+
 	if (Matches3("CREATE", "SEQUENCE", MatchAny))
 		COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
 							"CYCLE", "OWNED BY", "START WITH");
@@ -2034,9 +2109,16 @@ psql_completion_internal(const char *text, char **previous_words,
 	/* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
 	if (Matches2("CREATE", "TEMP|TEMPORARY"))
 		COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
+	HeadMatchAndRemove3(2, 1, "CREATE", "TEMP|TEMPORARY", "TABLE");
 	/* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
 	if (Matches2("CREATE", "UNLOGGED"))
 		COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
+	HeadMatchAndRemove3(2, 1, "CREATE", "UNLOGGED", MatchAny);
+	/* Complete CREATE TABLE with table names and IF NOT EXISTS */
+	if (Matches2("CREATE", "TABLE"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
+									  ADDLIST1("IF NOT EXISTS"));
+	HeadMatchAndRemove5(3, 3, "CREATE", "TABLE", "IF", "NOT", "EXISTS");
 
 /* CREATE TABLESPACE */
 	if (Matches3("CREATE", "TABLESPACE", MatchAny))
@@ -2164,6 +2246,13 @@ psql_completion_internal(const char *text, char **previous_words,
 /* CREATE MATERIALIZED VIEW */
 	if (Matches2("CREATE", "MATERIALIZED"))
 		COMPLETE_WITH_CONST("VIEW");
+	/* Complete CREATE MATERIALIZED VIEW with name or IF NOT EXISTS */
+	if (Matches3("CREATE", "MATERIALIZED", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews,
+									  ADDLIST1("IF NOT EXISTS"));
+	/* Remove IF NOT EXISTS */
+	HeadMatchAndRemove6(4, 3,
+				"CREATE", "MATERIALIZED", "VIEW", "IF", "NOT", "EXISTS");
 	/* Complete CREATE MATERIALIZED VIEW <name> with AS */
 	if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
 		COMPLETE_WITH_CONST("AS");
@@ -2209,9 +2298,86 @@ psql_completion_internal(const char *text, char **previous_words,
 		COMPLETE_WITH_CONST("LANGUAGE");
 
 /* DROP */
+	/* DROP INDEX */
+	if (Matches2("DROP", "INDEX"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
+									  ADDLIST2("CONCURRENTLY", "IF EXISTS"));
+	/* Remove CONCURRENTLY */
+	HeadMatchAndRemove3(3, 1, "DROP", "INDEX", "CONCURRENTLY");
+
+	if (Matches2("DROP", "AGGREGATE|COLLATION|CONVERSION|DOMAIN|EXTENSION|FUNCTION|GROUP|INDEX|LANGUAGE|POLICY|ROLE|SCHEMA|SEQUENCE|SERVER|TABLE|TABLESPACE|TRIGGER|TYPE|VIEW"))
+		COMPLETE_THING_KW(-1, ADDLIST1("IF EXISTS"));
+	/* Remove IF EXISTS */
+	HeadMatchAndRemove4(3, 2, "DROP", MatchAny, "IF", "EXISTS");
+
+	/* Complete more than two-words object names  */
+	/* DROP ACCESS METHOD */
+	if (Matches2("DROP", "ACCESS"))
+		COMPLETE_WITH_CONST("METHOD");
+	if (Matches3("DROP", "ACCESS", "METHOD"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_access_methods,
+							   ADDLIST1("IF EXISTS"));
+	/* DROP EVENT TRIGGER */
+	if (Matches2("DROP", "EVENT"))
+		COMPLETE_WITH_CONST("TRIGGER");
+	if (Matches3("DROP", "EVENT", "TRIGGER"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_event_triggers,
+							   ADDLIST1("IF EXISTS"));
+	/* DROP FOREIGN TABLE */
+	if (Matches2("DROP", "FOREIGN"))
+		COMPLETE_WITH_LIST2("TABLE", "DATA WRAPPER");
+	if (Matches3("DROP", "FOREIGN", "TABLE"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_foreign_tables,
+									  ADDLIST1("IF EXISTS"));
+	/* DROP FOREIGN DATA WRAPPER */
+	if (Matches3("DROP", "FOREIGN", "DATA"))
+		COMPLETE_WITH_CONST("WRAPPER");
+	if (Matches4("DROP", "FOREIGN", "DATA", "WRAPPER"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_fdws, ADDLIST1("IF EXISTS"));
+	/* DROP MATERIALIZED VIEW */
+	if (Matches2("DROP", "MATERIALIZED"))
+		COMPLETE_WITH_CONST("VIEW");
+	if (Matches3("DROP", "MATERIALIZED", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews,
+									  ADDLIST1("IF EXISTS"));
+	/* DROP PROCEDUAL LANGUAGE */
+	if (Matches2("DROP", "PROCEDUAL"))
+		COMPLETE_WITH_CONST("LANGUAGE");
+	if (Matches3("DROP", "PROCEDUAL", "LANGUAGE"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_languages,
+							   ADDLIST1("IF EXISTS"));
+	/* DROP USER, and USER MAPPING */
+	if (Matches2("DROP", "USER"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
+							   ADDLIST2("MAPPING", "IF EXISTS"));
+	if (Matches3("DROP", "USER", "MAPPING"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_user_mappings,
+							   ADDLIST2("IF EXISTS", "FOR"));
+
+	/* Remove IF EXISTS for two or three-words objects */
+	HeadMatchAndRemove5(4, 2, "DROP", MatchAny, MatchAny, "IF", "EXISTS");
+	HeadMatchAndRemove6(5, 2,
+						"DROP", MatchAny, MatchAny, MatchAny, "IF", "EXISTS");
+
+	if (Matches3("DROP", "ACCESS", "METHOD"))
+		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
+	if (Matches3("DROP", "EVENT", "TRIGGER"))
+		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
+	if (Matches3("DROP", "FOREIGN", "TABLE"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
+	if (Matches4("DROP", "FOREIGN", "DATA", "WRAPPER"))
+		COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
+	if (Matches3("DROP", "MATERIALIZED", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
+	if (Matches3("DROP", "PROCEDUAL", "LANGUAGE"))
+		COMPLETE_WITH_QUERY(Query_for_list_of_languages);
+	if (Matches4("DROP", "USER", "MAPPING", "FOR"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
+							   ADDLIST3("USER", "CURRENT_USER", "PUBLIC"));
+
 	/* Complete DROP object with CASCADE / RESTRICT */
 	if (Matches3("DROP",
-					  "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
+					  "COLLATION|CONVERSION|DOMAIN|EXTENSION|INDEX|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
 					  MatchAny) ||
 			 Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
 			 (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
@@ -2227,23 +2393,6 @@ psql_completion_internal(const char *text, char **previous_words,
 		COMPLETE_WITH_CONST("(");
 	if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
 		COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
-	if (Matches2("DROP", "FOREIGN"))
-		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
-
-	/* DROP INDEX */
-	if (Matches2("DROP", "INDEX"))
-		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
-									  ADDLIST1("CONCURRENTLY"));
-	/* Remove CONCURRENTLY */
-	HeadMatchAndRemove3(3, 1, "DROP", "INDEX", "CONCURRENTLY");
-	if (Matches3("DROP", "INDEX", MatchAny))
-		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
-
-	/* DROP MATERIALIZED VIEW */
-	if (Matches2("DROP", "MATERIALIZED"))
-		COMPLETE_WITH_CONST("VIEW");
-	if (Matches3("DROP", "MATERIALIZED", "VIEW"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
 
 	/* DROP OWNED BY */
 	if (Matches2("DROP", "OWNED"))
@@ -2266,21 +2415,6 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
 
-	/* DROP ACCESS METHOD */
-	if (Matches2("DROP", "ACCESS"))
-		COMPLETE_WITH_CONST("METHOD");
-	if (Matches3("DROP", "ACCESS", "METHOD"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
-
-	/* DROP EVENT TRIGGER */
-	if (Matches2("DROP", "EVENT"))
-		COMPLETE_WITH_CONST("TRIGGER");
-	if (Matches3("DROP", "EVENT", "TRIGGER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
-
-	/* DROP POLICY <name>  */
-	if (Matches2("DROP", "POLICY"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_policies);
 	/* DROP POLICY <name> ON */
 	if (Matches3("DROP", "POLICY", MatchAny))
 		COMPLETE_WITH_CONST("ON");
@@ -2848,6 +2982,9 @@ psql_completion_internal(const char *text, char **previous_words,
 /* USER MAPPING */
 	if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
 		COMPLETE_WITH_CONST("FOR");
+	if (Matches2("CREATE", "USER"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
+							   ADDLIST1("MAPPING FOR"));
 	if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
 		COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
 			ADDLIST3("CURRENT_USER", "PUBLIC", "USER"));
-- 
2.9.2

