($INBOX_DIR/description missing)  
help / color / mirror / Atom feed
From: Kyotaro Horiguchi <[email protected]>
Subject: [PATCH 5/6] Add suggestion for IF (NOT) EXISTS for some syntaxes
Date: Thu, 15 Sep 2016 20:49:45 +0900

Add suggestion for IF EXISTS or IF NOT EXISTS for some arbitrary
syntaxes, ALTER TABLE/ALTER FOREIGN TABLE/ALTER INDEX/
ALTER MATERIALIZED VIEW/ALTER DOMAIN DROP CONSTRAINT/ALTER SEQUENCE/
ALTER VIEW/ALTER POLICY/ALTER TABLE DROP COLUMN/
ALTER TABLE DROP CONSTRAINT/CREATE INDEX/CREATE SEQUENCE/
CREATE TABLE/CREATE VIEW/DROP INDEX/DROP (MATERIALIZED) VIEW/
DROP USER MAPPING
---
 src/bin/psql/tab-complete.c | 178 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 168 insertions(+), 10 deletions(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index ec5a700..cbac5d3 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1094,7 +1094,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"));
+	if (HeadMatches4("ALTER", "TABLE", "IF", "EXISTS"))
+		COLLAPSE(3, 2);
 
 	/* ALTER something */
 	if (Matches1("ALTER"))
@@ -1197,6 +1199,14 @@ 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 optional words for further completion */
+	if (HeadMatches5("ALTER", "FOREIGN", "TABLE", "IF", "EXISTS"))
+		COLLAPSE(4, 2);
+
 	/* ALTER FOREIGN TABLE <name> */
 	if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
 	{
@@ -1211,7 +1221,11 @@ 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 optional words for further completion */
+	if (HeadMatches4("ALTER", "INDEX", "IF", "EXISTS"))
+		COLLAPSE(3, 2);
+
 	/* ALTER INDEX <name> */
 	if (Matches3("ALTER", "INDEX", MatchAny))
 		COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
@@ -1240,7 +1254,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 optional words for further completion */
+	if (HeadMatches5("ALTER", "MATERIALIZED", "VIEW", "IF", "EXISTS"))
+		COLLAPSE(4, 2);
 
 	/* ALTER USER,ROLE <name> */
 	if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
@@ -1296,6 +1313,19 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
+		if (word_matches("DROP", prev2_wd))
+			COMPLETE_WITH_QUERY_KW(Query_for_constraint_of_type,
+								   ADDLIST1("IF EXISTS"));
+		else
+			COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
+	}
+	/* Remove optional words for further completion */
+	if (HeadMatches7("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT", "IF", "EXISTS"))
+		COLLAPSE(6, 2);
+	/*  Complete constraint name again without IF EXISTS */
+	if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT"))
+	{
+		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
 	}
 	/* ALTER DOMAIN <sth> RENAME */
@@ -1308,6 +1338,16 @@ psql_completion_internal(const char *text, char **previous_words,
 	/* ALTER DOMAIN <sth> SET */
 	if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
 		COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
+	/* ALTER SEQUENCE */
+	if (Matches2("ALTER", "SEQUENCE"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_sequences,
+									  ADDLIST1("IF EXISTS"));
+	/* Remove optional words for further completion */
+	if (HeadMatches4("ALTER", "SEQUENCE", "IF", "EXISTS"))
+		COLLAPSE(3, 2);
+	/* Complete again without IF EXISTS */
+	if (Matches2("ALTER", "SEQUENCE"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
 	/* ALTER SEQUENCE <name> */
 	if (Matches3("ALTER", "SEQUENCE", MatchAny))
 	{
@@ -1333,6 +1373,16 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
 		COMPLETE_WITH_QUERY_KW(Query_for_list_of_alter_system_set_vars,
 							   ADDLIST1("ALL"));
+	/* ALTER VIEW */
+	if (Matches2("ALTER", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views,
+									  ADDLIST1("IF EXISTS"));
+	/* Remove optional words for further completion */
+	if (HeadMatches4("ALTER", "VIEW", "IF", "EXISTS"))
+		COLLAPSE(3, 2);
+	/* Complete again without IF EXISTS */
+	if (Matches2("ALTER", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
 	/* ALTER VIEW <name> */
 	if (Matches3("ALTER", "VIEW", MatchAny))
 		COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
@@ -1344,6 +1394,12 @@ psql_completion_internal(const char *text, char **previous_words,
 
 	/* ALTER POLICY <name> */
 	if (Matches2("ALTER", "POLICY"))
+		COMPLETE_WITH_QUERY_KW(Query_for_list_of_policies, ADDLIST1("IF EXISTS"));
+	/* Remove optional words for further completion */
+	if (Matches4("ALTER", "POLICY", "IF", "EXISTS"))
+		COLLAPSE(3, 2);
+	/* Complete again without IF EXISTS */
+	if (Matches2("ALTER", "POLICY"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_policies);
 	/* ALTER POLICY <name> ON */
 	if (Matches3("ALTER", "POLICY", MatchAny))
@@ -1483,8 +1539,13 @@ psql_completion_internal(const char *text, char **previous_words,
 		COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
 	/* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
 	if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
+		COMPLETE_WITH_ATTR_KW(prev3_wd, ADDLIST1("IF EXISTS"));
+	/* Remove optional words for further completion */
+	if (HeadMatches7("ALTER", "TABLE", MatchAny, "DROP", "COLUMN", "IF", "EXISTS"))
+		COLLAPSE(6, 2);
+	/* Complete again without IF EXISTS */
+	if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
 		COMPLETE_WITH_ATTR(prev3_wd);
-
 	/*
 	 * If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
 	 * provide list of constraints
@@ -1492,6 +1553,19 @@ psql_completion_internal(const char *text, char **previous_words,
 	if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
+		if (word_matches("DROP", prev2_wd))
+			COMPLETE_WITH_QUERY_KW(Query_for_constraint_of_table,
+								ADDLIST1("IF EXISTS"));
+		else
+			COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
+	}
+	/* Remove IF EXISTS for further completion */
+	if (HeadMatches7("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT", "IF", "EXISTS"))
+		COLLAPSE(6, 2);
+	/* Complete again without IF EXISTS */
+	if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT"))
+	{
+		completion_info_charp = prev3_wd;
 		COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
 	}
 	/* Remove COLUMN just after ALTER */
@@ -1633,7 +1707,18 @@ psql_completion_internal(const char *text, char **previous_words,
 	 * of attributes
 	 */
 	if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
-		COMPLETE_WITH_ATTR(prev3_wd);
+	{
+		if (word_matches("DROP", prev2_wd))
+			COMPLETE_WITH_ATTR_KW(prev3_wd, ADDLIST1("IF EXISTS"));
+		else
+			COMPLETE_WITH_ATTR(prev3_wd);
+	}
+	/* Remove IF EXISTS for further completion */
+	if (HeadMatches7("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE", "IF", "EXISTS"))
+		COLLAPSE(6, 2);
+	/* Complete again without IF EXISTS */
+	if (Matches5("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE"))
+			COMPLETE_WITH_ATTR(prev3_wd);	
 	/* ALTER TYPE ALTER ATTRIBUTE <foo> */
 	if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
 		COMPLETE_WITH_CONST("TYPE");
@@ -1787,6 +1872,13 @@ 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 for further completion*/
+	if (HeadMatches5("CREATE", "EXTENSION", "IF", "NOT", "EXISTS"))
+		COLLAPSE(3, 3);
+	/* Complete again without IF NOT EXISTS */
+	if (Matches2("CREATE", "EXTENSION"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
 	/* CREATE EXTENSION <name> */
 	if (Matches3("CREATE", "EXTENSION", MatchAny))
@@ -1817,14 +1909,20 @@ psql_completion_internal(const char *text, char **previous_words,
 	/* Complete with index names as category suggestion and possible keywords */
 	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 */
 	if (HeadMatches3("CREATE", "INDEX", "CONCURRENTLY"))
 		COLLAPSE(3, 1);
 	/* Complete with existing index names as word category suggestion */
 	if (Matches2("CREATE", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
-									  ADDLIST1("ON"));
+									  ADDLIST2("ON", "IF NOT EXISTS"));
+	/* Remove IF NOT EXISTS for further completion */
+	if (HeadMatches5("CREATE", "INDEX", "IF", "NOT", "EXISTS"))
+		COLLAPSE(3, 3);
+	/* Complete again without IF NOT EXISTS */
+	if (Matches2("CREATE", "INDEX"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
 	/* Suggest ON just after index name */
 	if (Matches3("CREATE", "INDEX", MatchAnyExcept("ON")))
 		COMPLETE_WITH_CONST("ON");
@@ -1917,6 +2015,13 @@ psql_completion_internal(const char *text, char **previous_words,
 
 	/* CREATE SEQUENCE */
 	if (Matches2("CREATE", "SEQUENCE"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_sequences,
+									  ADDLIST1("IF NOT EXISTS"));
+	/* Remove IF NOT EXISTS for further completion */
+	if (HeadMatches5("CREATE", "SEQUENCE", "IF", "NOT", "EXISTS"))
+		COLLAPSE(3, 3);
+	/* Complete again without IF NOT EXISTS */
+	if (Matches2("CREATE", "SEQUENCE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
 	if (Matches3("CREATE", "SEQUENCE", MatchAny))
 		COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
@@ -1942,6 +2047,13 @@ psql_completion_internal(const char *text, char **previous_words,
 		COLLAPSE(2, 1);
 	/* Complete CREATE TABLE with existing table names */
 	if (Matches2("CREATE", "TABLE"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
+									  ADDLIST1("IF NOT EXISTS"));
+	/* Remove IF NOT EXIST for further completion */
+	if (HeadMatches5("CREATE", "TABLE", "IF", "NOT", "EXISTS"))
+		COLLAPSE(3, 3);
+	/* Complete again without IF NOT EXISTS */
+	if (Matches2("CREATE", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
 
 /* CREATE TABLESPACE */
@@ -2134,6 +2246,16 @@ psql_completion_internal(const char *text, char **previous_words,
 		COMPLETE_WITH_LIST2("GROUP", "ROLE");
 
 /* CREATE VIEW */
+	/* Complete CREATE VIEW with name */
+	if (Matches2("CREATE", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views,
+									  ADDLIST1("IF NOT EXISTS"));
+	/* Remove IF NOT EXISTS for further completion */
+	if (HeadMatches5("CREATE", "VIEW", "IF", "NOT", "EXISTS"))
+		COLLAPSE(3, 3);
+	/* Complete again without IF NOT EXISTS */
+	if (Matches2("CREATE", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
 	/* Complete CREATE VIEW <name> with AS */
 	if (Matches3("CREATE", "VIEW", MatchAny))
 		COMPLETE_WITH_CONST("AS");
@@ -2213,18 +2335,43 @@ psql_completion_internal(const char *text, char **previous_words,
 	/* DROP INDEX */
 	if (Matches2("DROP", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
-									  ADDLIST1("CONCURRENTLY"));
+									  ADDLIST2("CONCURRENTLY", "IF EXISTS"));
+		if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
+			COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
+										  ADDLIST1("IF EXISTS"));
 	if (HeadMatches3("DROP", "INDEX", "CONCURRENTLY"))
 		COLLAPSE(3, 1);
+	/* Remove IF EXISTS for further completion */
+	if (HeadMatches4("DROP", "INDEX", "IF", "EXISTS"))
+		COLLAPSE(3, 2);
+	/* Complete again without IF EXISTS */
+	if (Matches2("DROP", "INDEX"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
 	if (Matches3("DROP", "INDEX", MatchAny))
 		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
 
+	/* DROP VIEW */
+	if (Matches2("DROP", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views,
+									  ADDLIST1("IF EXISTS"));
+	/* Remove IF EXISTS for further completion */
+	if (HeadMatches4("DROP", "VIEW", "IF", "EXISTS"))
+		COLLAPSE(3, 2);
+	/* Complet again without IF EXISTS */
+	if (Matches2("DROP", "VIEW"))
+		COMPLETE_THING(-1);
+
 	/* DROP MATERIALIZED VIEW */
 	if (Matches2("DROP", "MATERIALIZED"))
 		COMPLETE_WITH_CONST("VIEW");
 
-	/* DROP VIEW is suggested as a general thing */
-
+	if (Matches3("DROP", "MATERIALIZED", "VIEW"))
+		COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews,
+									  ADDLIST1("IF EXISTS"));
+	/* Remove IF EXISTS for further completion */
+	if (HeadMatches5("DROP", "MATERIALIZED", "VIEW", "IF", "EXISTS"))
+		COLLAPSE(4, 2);
+	/* Complet again without IF EXISTS */
 	if (Matches3("DROP", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
 
@@ -2791,6 +2938,17 @@ psql_completion_internal(const char *text, char **previous_words,
 
 /* USER MAPPING */
 	if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
+	{
+		if (word_matches("DROP", prev3_wd))
+			COMPLETE_WITH_LIST2("FOR", "IF EXISTS FOR");
+		else
+			COMPLETE_WITH_CONST("FOR");
+	}
+	/* Remove IF EXISTS for further completion */
+	if (HeadMatches5("DROP", "USER", "MAPPING", "IF", "EXISTS"))
+		COLLAPSE(4, 2);
+	/* Complete again without IF EXISTS */
+	if (Matches3("DROP", "USER", "MAPPING"))
 		COMPLETE_WITH_CONST("FOR");
 	if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
 		COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
-- 
2.9.2


----Next_Part(Tue_Nov_15_20_26_42_2016_708)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="0006-Add-README-for-tab-completion.patch"



view thread (3+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected]
  Subject: Re: [PATCH 5/6] Add suggestion for IF (NOT) EXISTS for some syntaxes
  In-Reply-To: <no-message-id-66725@localhost>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox