Hello, I returned to this since Thomas' psql-completion patch has
been committed.

This patch has been recreated on it.

"IN TABLESPACE xxx OWNED BY" has been alredy fixed so I removed it.
The attched files are the following,

1. 0001-Fix-tab-complete-of-CREATE-INDEX.patch

  Fixes completion for CREATE INDEX in ordinary way.

2. 0001-Fix-completion-for-CREATE-INDEX-type-2.patch

  An alternative for 1. Introduces multilevel matching. This
  effectively can avoid false matching, simplify each expression
  and reduce the number of matching operations.

3. 0002-Fix-tab-completion-for-DROP-INDEX.patch

  Fix of DROP INDEX completion in the type-2 way.

=====
At Tue, 08 Dec 2015 17:56:19 +0900 (Tokyo Standard Time), Kyotaro HORIGUCHI 
<horiguchi.kyot...@lab.ntt.co.jp> wrote in 
<20151208.175619.245979824.horiguchi.kyot...@lab.ntt.co.jp>
> > I tested whether the following patterns work as expected or not.
> > 
> > CREATE UNIQUE INDEX CONCURRENTLY name ON
> > CREATE UNIQUE INDEX CONCURRENTLY ON
> > CREATE UNIQUE INDEX name ON
> > CREATE UNIQUE INDEX ON
> > CREATE INDEX CONCURRENTLY name ON
> > CREATE INDEX CONCURRENTLY ON
> > CREATE INDEX name ON
> > CREATE INDEX ON
> > 
> > Then I found the following problems.
> > 
> > "CREATE UNIQUE INDEX CONCURRENTLY <tab>" didn't suggest "ON".
> > "CREATE UNIQUE INDEX ON <tab>" suggested nothing.
> > "CREATE INDEX ON <tab>" suggested nothing.

All of the cases above are completed correctly. As a new feature,
this patch allows "IF NOT EXISTS". As the result, the following
part of the syntax of CREATE INDEX is completed correctly.

CREATE [UNIQUE] INDEX [CONCURRENTLY] [[IF NOT EXISTS] iname] ON tname

> > "CREATE INDEX CONCURRENTLY <tab>" didn't suggest "ON".

Now it suggests "ON", "IF NOT EXISTS" and existing index names.

> > BTW, I found that tab-completion for DROP INDEX has the following problems.
> > 
> > "DROP INDEX <tab>" didn't suggest "CONCURRENTLY".
> > "DROP INDEX CONCURRENTLY name <tab>" suggested nothing.

They are completed by the "things" completion. The first patch
gives a wrong suggestion for DROP INDEX CONCURRENTLY with "IF NOT
EXISTS". This can be avoided adding HeadMatches to every matching
for "CREATE INDEX..." syntexes but it is too bothersome.

Instaed, in the second alternative patch, I enclosed the whole
"CREATE INDEX" stuff by an if(HeadMatches2("CREATE",
"UNIQUE|INDEX")) block to avoid the false match and simplify each
matching expression. As a side effect, the total number of the
executions of matching expressions can be reduced. (This wouldn't
be just a bug fix, but rarther a kind of refactoring.)

The third patch fixes the behavior for DROP INDEX in this way.

Thoughs? Suggestions?

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
>From 5488edb6ebdd253b1a10179ac119cc1588459791 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyot...@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

>From ac65ecdc92fcae899d13b7b6df51211f6cc7e69d Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyot...@lab.ntt.co.jp>
Date: Tue, 22 Dec 2015 12:34:13 +0900
Subject: [PATCH 1/2] Fix completion for CREATE INDEX type 2.

This patch introduces multilevel matching for completion. This can
simplify individual matching and make it easier to avoid false
matching.
---
 src/bin/psql/tab-complete.c | 103 ++++++++++++++++++++++++++++----------------
 1 file changed, 65 insertions(+), 38 deletions(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 1a7d184..fb3833b 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1918,45 +1918,72 @@ psql_completion(const char *text, int start, int end)
 	/* First off we complete CREATE UNIQUE with "INDEX" */
 	else if (TailMatches2("CREATE", "UNIQUE"))
 		COMPLETE_WITH_CONST("INDEX");
-	/* If we have CREATE|UNIQUE INDEX, then add "ON" and existing indexes */
-	else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
-								   " UNION SELECT 'ON'"
-								   " 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"))
-		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 <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))
-		COMPLETE_WITH_LIST2("(", "USING");
-	else if (TailMatches5("INDEX", 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"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
-	else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
-			 !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
-			 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
-		COMPLETE_WITH_CONST("(");
+	/* Completion for CREATE INDEX */
+	else if (HeadMatches2("CREATE", "UNIQUE|INDEX"))
+	{
+		/* If we have CREATE|UNIQUE INDEX, then add "ON" and existing indexes */
+		if (TailMatches1("INDEX"))
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
+									   " UNION SELECT 'ON'"
+									   " UNION SELECT 'IF NOT EXISTS'"
+									   " UNION SELECT 'CONCURRENTLY'");
+		/*
+		 * If we have CREATE [UNIQUE] INDEX [CONCURRENTLY], suggest existing
+		 * indexes or ON/IF NOT EXISTS.
+		 */
+		else if (TailMatches1("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 (TailMatches3("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 (TailMatches4("IF", "NOT", "EXISTS", MatchAny) ||
+				 TailMatches2("INDEX|CONCURRENTLY", "!ON"))
+			COMPLETE_WITH_CONST("ON");
+
+		/*
+		 * Complete ... INDEX [[IF NOT EXISTS] <name>] ON with a list of
+		 * tables
+		 */
+		else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
+				 TailMatches2("INDEX|CONCURRENTLY", "ON") ||
+				 TailMatches5("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 (TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny) ||
+				 TailMatches4("INDEX|CONCURRENTLY", MatchAny, "ON", MatchAny) ||
+				 TailMatches6("IF", "NOT", "EXISTS", MatchAny, "ON", MatchAny))
+			COMPLETE_WITH_LIST2("(", "USING");
+		else if (TailMatches5("INDEX|CONCURRENTLY", MatchAny,
+							  "ON", MatchAny, "(") ||
+				 TailMatches7("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 (TailMatches3("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) &&
+				 !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
+			COMPLETE_WITH_CONST("(");
+	} /* CREATE [UNIQUE] INDEX */
 
 	/* CREATE POLICY */
 	/* Complete "CREATE POLICY <name> ON" */
-- 
1.8.3.1

>From d3afe85dded940d67480f305aecb6ab9fb4f9503 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyot...@lab.ntt.co.jp>
Date: Tue, 22 Dec 2015 12:51:41 +0900
Subject: [PATCH 2/2] Fix tab completion for DROP INDEX

DROP INDEX didn't get suggestions of "CONCURRENTLY", or "IF
EXISTS". This patch introduces such suggestions.
---
 src/bin/psql/tab-complete.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index fb3833b..45bee03 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -2199,7 +2199,7 @@ psql_completion(const char *text, int start, int end)
 /* DROP (when not the previous word) */
 	/* DROP object with CASCADE / RESTRICT */
 	else if (TailMatches3("DROP",
-						  "COLLATION|CONVERSION|DOMAIN|EXTENSION|INDEX|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
+						  "COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
 						  MatchAny) ||
 		   (TailMatches4("DROP", "AGGREGATE|FUNCTION", MatchAny, MatchAny) &&
 			ends_with(prev_wd, ')')) ||
@@ -2217,6 +2217,22 @@ psql_completion(const char *text, int start, int end)
 	else if (TailMatches2("DROP", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
 
+	/* DROP INDEX */
+	else if (HeadMatches2("DROP", "INDEX"))
+	{
+		if (TailMatches1("INDEX"))
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
+									   " UNION SELECT 'IF EXISTS'"
+									   " UNION SELECT 'CONCURRENTLY'");
+		else if (TailMatches1("CONCURRENTLY"))
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
+									   " UNION SELECT 'IF EXISTS'");
+		else if (TailMatches2("IF", "EXISTS"))
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+		else 
+			COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
+	}
+
 	/* DROP MATERIALIZED VIEW */
 	else if (TailMatches2("DROP", "MATERIALIZED"))
 		COMPLETE_WITH_CONST("VIEW");
-- 
1.8.3.1

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to