>From 5488edb6ebdd253b1a10179ac119cc1588459791 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Tue, 22 Dec 2015 11:03:16 +0900
Subject: [PATCH] Fix tab-complete of CREATE INDEX

Completion for CREATE INDEX added CONCURRENLTY into wrong place, and
it didn't suggest "IF NOT EXISTS". This patch corrects and adds them.
---
 src/bin/psql/tab-complete.c | 59 +++++++++++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 16 deletions(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 1a7d184..9f557b3 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1922,36 +1922,63 @@ psql_completion(const char *text, int start, int end)
 	else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
 								   " UNION SELECT 'ON'"
+								   " UNION SELECT 'IF NOT EXISTS'"
 								   " UNION SELECT 'CONCURRENTLY'");
-	/* Complete ... INDEX [<name>] ON with a list of tables  */
-	else if (TailMatches3("INDEX", MatchAny, "ON") ||
-			 TailMatches2("INDEX|CONCURRENTLY", "ON"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
-	/* If we have CREATE|UNIQUE INDEX <sth> CONCURRENTLY, then add "ON" */
-	else if (TailMatches3("INDEX", MatchAny, "CONCURRENTLY") ||
-			 TailMatches2("INDEX", "CONCURRENTLY"))
+	/*
+	 * If we have CREATE [UNIQUE] INDEX [CONCURRENTLY], suggest existing
+	 * indexes or ON/IF NOT EXISTS.
+	 */
+	else if (TailMatches2("INDEX", "CONCURRENTLY"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
+								   " UNION SELECT 'ON'"
+								   " UNION SELECT 'IF NOT EXISTS'");
+	/*
+	 * If we have CREATE [UNIQUE] INDEX [CONCURRENTLY] IF NOT EXISTS, suggest
+	 * existing indexes
+	 */
+	else if (TailMatches4("INDEX|CONCURRENTLY", "IF", "NOT", "EXISTS"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+	/*
+	 * If we have CREATE [UNIQUE] INDEX [CONCURRENTLY] [IF NOT EXISTS sth],
+	 * then add "ON"
+	 */
+	else if (TailMatches5("INDEX|CONCURRENTLY",
+						  "IF", "NOT", "EXISTS", MatchAny) ||
+			 TailMatches2("INDEX|CONCURRENTLY", "!ON"))
 		COMPLETE_WITH_CONST("ON");
-	/* If we have CREATE|UNIQUE INDEX <sth>, then add "ON" or "CONCURRENTLY" */
-	else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny))
-		COMPLETE_WITH_LIST2("CONCURRENTLY", "ON");
+
+	/* Complete ... INDEX [[IF NOT EXISTS] <name>] ON with a list of tables  */
+	else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
+			 TailMatches2("INDEX|CONCURRENTLY", "ON") ||
+			 TailMatches6("INDEX|CONCURRENTLY", 
+						  "IF", "NOT", "EXISTS", MatchAny, "ON"))
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
 
 	/*
 	 * Complete INDEX <name> ON <table> with a list of table columns (which
 	 * should really be in parens)
 	 */
-	else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
-			 TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
+	else if (TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny) ||
+			 TailMatches4("INDEX|CONCURRENTLY", MatchAny, "ON", MatchAny) ||
+			 TailMatches7("INDEX|CONCURRENTLY",
+						  "IF", "NOT", "EXISTS", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST2("(", "USING");
-	else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
+	else if (TailMatches5("INDEX|CONCURRENTLY", MatchAny,
+						  "ON", MatchAny, "(") ||
+			 TailMatches8("INDEX|CONCURRENTLY", "IF", "NOT", "EXISTS", MatchAny,
+						  "ON", MatchAny, "(") ||
 			 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
 		COMPLETE_WITH_ATTR(prev2_wd, "");
 	/* same if you put in USING */
 	else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
 		COMPLETE_WITH_ATTR(prev4_wd, "");
 	/* Complete USING with an index method */
-	else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
-			 TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
-			 TailMatches4("INDEX", "ON", MatchAny, "USING"))
+	else if (TailMatches5("INDEX|CONCURRENTLY", MatchAny,
+						  "ON", MatchAny, "USING") ||
+			 TailMatches8("INDEX|CONCURRENTLY",
+						  "IF", "NOT", "EXISTS", MatchAny,
+						  "ON", MatchAny, "USING") ||
+			 TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "USING"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
 	else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
 			 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
-- 
1.8.3.1

