Hello,

At Tue, 29 Mar 2016 13:12:06 +0200, Pavel Stehule <pavel.steh...@gmail.com> 
wrote in <CAFj8pRCnrpdSqSozg4Y8__2LFyiNqUCE=kpzfw1+af_lutm...@mail.gmail.com>
> 2016-03-29 12:08 GMT+02:00 Kyotaro HORIGUCHI <
> > > > As mentioned before, upper-lower problem is an existing
> > > > issue. The case of the words in a query result list cannot be
> > > > edited since it may contain words that should not be changed,
> > > > such as relation names. So we can address it only before issueing
> > > > a query but I haven't found simple way to do it.
> > > >
> > >
> > > This is unpleasant. I am sorry. I had very uncomfortable feeling from
> > this
> > > behave. I am thinking so it should be solvable - you have to convert only
> > > keyword IF EXISTS or IF NOT EXISTS. Maybe there are not trivial solution,
> > > but this should be fixed.
> >
> > I understand that and feel the same. But I don't want to put
> > puzzling code. Defining a macro enable this by writing as the
> > following.
> >
> 
> puzzle is wrong, but nonconsistent behave is not acceptable

Mmm. Ok, The attched patch, which applies on top of the
IF(NOT)EXIST patch, does this in rather saner appearance, but
needs to run additional C function at runtime and additional some
macros. The function is called up to once per completion, so it
won't be a performance problem.

>    else if (Matches2("ALTER", "TABLE"))
>        COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
>            ADDLIST2("", "IF EXISTS", "ALL IN TABLESPACE"));

or

>    else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT"))
>    {
>        completion_info_charp = prev3_wd;
>        COMPLETE_WITH_QUERY(
>            ADDLIST1(Query_for_constraint_of_table, "IF EXISTS"));
>    }

I think this syntax is acceptable. Only keywords follows the
setting of COMP_KEYWORD_CASE, as Artur suggested.

=# alter table <tab>
ALL IN TABLESPACE    pg_catalog.          public.
alpha.               pg_temp_1.           x
IF EXISTS            pg_toast.            
information_schema.  pg_toast_temp_1.     
=# alter table i<tab>
if exists
information_schema.sql_features
...
=# alter table if<tab>
=# alter table if exists 
======
=# alter table I<tab>
=# alter table IF EXISTS    // "information_schema" doesn't match.

Since this is another problem from IF (NOT) EXISTS, this is
in separate form.

What do you think about this?

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
>From 282266477b2dfbc6c35a8a4da49544eb9cbfb6fe Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyot...@lab.ntt.co.jp>
Date: Tue, 29 Mar 2016 19:01:13 +0900
Subject: [PATCH] Make appended keywords of completion queries follow to input.

Currently some keyword shown along with database objects are always in
upper case. This patch changes the behavior so that the case of the
additional keywords follow the setting of COMP_KEYWORD_CASE.
---
 src/bin/psql/tab-complete.c | 231 +++++++++++++++++++++++++-------------------
 1 file changed, 132 insertions(+), 99 deletions(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 73c5601..e48bd2f 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -312,6 +312,18 @@ do { \
 	COMPLETE_WITH_LIST_CS(list); \
 } while (0)
 
+#define ADDLIST1(p, s1) additional_kw_query(p, text, 1, s1)
+#define ADDLIST2(p, s1, s2) additional_kw_query(p, text, 2, s1, s2)
+#define ADDLIST3(p, s1, s2, s3) additional_kw_query(p, text, 3, s1, s2, s3)
+#define ADDLIST4(p, s1, s2, s3, s4) \
+	additional_kw_query(p, text, 4, s1, s2, s3, s4)
+#define ADDLIST13(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13) \
+	additional_kw_query(p, text, 12, s1, s2, s3, s4, s5, s6, s7,		\
+						s8, s9, s10, s11, s12, s13)
+#define ADDLIST15(p, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15) \
+	additional_kw_query(p, text, 12, s1, s2, s3, s4, s5, s6, s7,		\
+						s8, s9, s10, s11, s12, s13, s14, s15)
+
 /*
  * Assembly instructions for schema queries
  */
@@ -955,6 +967,7 @@ static char *complete_from_files(const char *text, int state);
 
 static int find_last_index_of(char *w, char **previous_words, int len);
 static char *pg_strdup_keyword_case(const char *s, const char *ref);
+static char *additional_kw_query(char *prefix, const char *ref, int n, ...);
 static char *escape_string(const char *text);
 static PGresult *exec_query(const char *query);
 
@@ -1438,8 +1451,8 @@ psql_completion(const char *text, int start, int end)
 	/* ALTER TABLE */
 	else if (Matches2("ALTER", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
-								   "UNION SELECT 'IF EXISTS'"
-								   "UNION SELECT 'ALL IN TABLESPACE'");
+			ADDLIST2("", "IF EXISTS", "ALL IN TABLESPACE"));
+
 	/* Try ALTER TABLE after removing optional words IF EXISTS*/
 	else if (HeadMatches2("ALTER", "TABLE") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -1525,7 +1538,7 @@ psql_completion(const char *text, int start, int end)
 	/* ALTER FOREIGN TABLE */
 	else if (Matches3("ALTER|DROP", "FOREIGN", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables,
-								   " UNION SELECT 'IF EXISTS'");
+								   ADDLIST1("", "IF EXISTS"));
 
 	/* Try ALTER FOREIGN TABLE after removing optinal words IF EXISTS */
 	/* Complete for DROP together  */
@@ -1552,8 +1565,7 @@ psql_completion(const char *text, int start, int end)
 	/* ALTER INDEX */
 	else if (Matches2("ALTER", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
-								   "UNION SELECT 'IF EXISTS'"
-								   "UNION SELECT 'ALL IN TABLESPACE'");
+			   ADDLIST2("", "IF EXISTS", "ALL IN TABLESPACE"));
 	/* Try ALTER INDEX after removing optional words IF EXISTS */
 	else if (HeadMatches2("ALTER", "INDEX") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -1588,8 +1600,7 @@ psql_completion(const char *text, int start, int end)
 	/* ALTER MATERIALIZED VIEW */
 	else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
-								   "UNION SELECT 'IF EXISTS'"
-								   "UNION SELECT 'ALL IN TABLESPACE'");
+			   ADDLIST2("", "IF EXISTS", "ALL IN TABLESPACE"));
 
 	/* Try ALTER MATERIALIZED VIEW after removing optional words IF EXISTS */
 	else if (HeadMatches3("ALTER", "MATERIALIZED", "VIEW") &&
@@ -1657,8 +1668,8 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_constraint_of_type
-							"UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_constraint_of_type, "IF EXISTS"));
 	}
 	/* Try the same match after removing optional words IF EXISTS */
 	else if (HeadMatches5("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT") &&
@@ -1680,7 +1691,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
 	else if (Matches2("ALTER", "SEQUENCE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences,
-								   " UNION SELECT 'IF EXISTS'");
+								   ADDLIST1("", "IF EXISTS"));
 	/* Try ALTER SEQUENCE after removing optional words IF EXISTS */
 	else if (HeadMatches2("ALTER", "SEQUENCE") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -1710,7 +1721,7 @@ psql_completion(const char *text, int start, int end)
 	/* ALTER VIEW */
 	else if (Matches2("ALTER", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views,
-								   "UNION SELECT 'IF EXISTS'");
+								   ADDLIST1("", "IF EXISTS"));
 	/*  Try ALTER VIEW after removing optional worlds IF EXISTS */
 	else if (HeadMatches2("ALTER", "VIEW") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -1726,8 +1737,8 @@ psql_completion(const char *text, int start, int end)
 
 	/* ALTER POLICY */
 	else if (Matches2("ALTER", "POLICY"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_policies
-							"UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_list_of_policies, "IF EXISTS"));
 	/* Try ALTER POLICY after removing optional words IF EXISTS */
 	else if (HeadMatches2("ALTER", "POLICY") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -1904,8 +1915,8 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_constraint_of_table
-							"UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_constraint_of_table, "IF EXISTS"));
 	}
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches5("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT") &&
@@ -2099,7 +2110,8 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
 /* CLUSTER */
 	else if (Matches1("CLUSTER"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
+								   ADDLIST1("", "VERBOSE"));
 	else if (Matches2("CLUSTER", "VERBOSE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
 	/* If we have CLUSTER <sth>, then add "USING" */
@@ -2161,7 +2173,7 @@ psql_completion(const char *text, int start, int end)
 	 */
 	else if (Matches1("COPY|\\copy"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
-								   " UNION ALL SELECT '('");
+								   ADDLIST1("", "("));
 	/* If we have COPY BINARY, complete with list of tables */
 	else if (Matches2("COPY", "BINARY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
@@ -2229,7 +2241,7 @@ psql_completion(const char *text, int start, int end)
 	/* CREATE FOREIGN TABLE */
 	else if (Matches3("CREATE", "FOREIGN", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables,
-								   " UNION SELECT 'IF NOT EXISTS'");
+								   ADDLIST1("", "IF NOT EXISTS"));
 	/* Remove optional words IF NOT EXISTS */
 	else if (HeadMatches3("CREATE", "FOREIGN", "TABLE") &&
 			 MidMatchAndRemove3(3, "IF", "NOT", "EXISTS") &&
@@ -2252,15 +2264,12 @@ psql_completion(const char *text, int start, int end)
 	   and existing indexes */
 	else if (Matches2("CREATE", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
-								   " UNION SELECT 'ON'"
-								   " UNION SELECT 'CONCURRENTLY'"
-								   " UNION SELECT 'IF NOT EXISTS'");
+				   ADDLIST3("", "ON", "CONCURRENTLY", "IF NOT EXISTS"));
 	/* Complete CREATE INDEX CONCURRENTLY with "ON" or IF NOT EXISTS and
 	 * existing indexes */
 	else if (Matches3("CREATE", "INDEX", "CONCURRENTLY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
-								   " UNION SELECT 'IF NOT EXISTS'"
-								   " UNION SELECT 'ON'");
+								   ADDLIST2("", "IF NOT EXISTS", "ON"));
 
 	/* Remove optional words "CONCURRENTLY",  "IF NOT EXISTS" */
 	else if (HeadMatches2("CREATE", "INDEX") &&
@@ -2367,8 +2376,8 @@ psql_completion(const char *text, int start, int end)
 
 /* CREATE SCHEMA <name> */
 	else if (Matches2("CREATE", "SCHEMA"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_schemas
-							" UNION SELECT 'IF NOT EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_list_of_schemas, "IF NOT EXISTS"));
 	/* Remove optional words IF NOT EXISTS */
 	else if (HeadMatches2("CREATE", "SCHEMA") &&
 			 MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") &&
@@ -2389,7 +2398,7 @@ psql_completion(const char *text, int start, int end)
 
 	else if (Matches2("CREATE", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
-								   " UNION SELECT 'IF NOT EXISTS'");
+								   ADDLIST1("", "IF NOT EXISTS"));
 
 	/* Remove optional words here */
 	else if (HeadMatches2("CREATE", "TABLE") &&
@@ -2480,7 +2489,7 @@ psql_completion(const char *text, int start, int end)
 /* CREATE VIEW  */
 	else if (Matches2("CREATE", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views,
-								   " UNION SELECT 'IF NOT EXISTS'");
+								   ADDLIST1("", "IF NOT EXISTS"));
 	/* Remove optional words IF NOT EXISTS */
 	else if (HeadMatches2("CREATE", "VIEW") &&
 			 MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") &&
@@ -2497,7 +2506,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("VIEW");
 	else if (Matches3("CREATE", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
-								   " UNION SELECT 'IF NOT EXISTS'");
+								   ADDLIST1("", "IF NOT EXISTS"));
 	/* Try the same after removing optional words IF NOT EXISTS. VIEW will be
 	 * completed afterwards */
 	else if (HeadMatches3("CREATE", "MATERIALIZED", "VIEW") &&
@@ -2564,10 +2573,10 @@ psql_completion(const char *text, int start, int end)
 	/* help completing some of the variants */
 	else if (Matches2("DROP", "AGGREGATE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates,
-								   " UNION SELECT 'IF EXISTS'");
+								   ADDLIST1("", "IF EXISTS"));
 	else if (Matches2("DROP", "FUNCTION"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions,
-								   " UNION SELECT 'IF EXISTS'");
+								   ADDLIST1("", "IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches2("DROP", "AGGREGATE|FUNCTION") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -2578,8 +2587,8 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches2("DROP", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
 	else if (Matches4("DROP", "FOREIGN", "DATA", "WRAPPER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_fdws
-							" UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_list_of_fdws, "IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches4("DROP", "FOREIGN", "DATA", "WRAPPER") &&
 			 MidMatchAndRemove2(4, "IF", "EXISTS") &&
@@ -2588,11 +2597,10 @@ psql_completion(const char *text, int start, int end)
 	/* DROP INDEX */
 	else if (Matches2("DROP", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
-								   " UNION SELECT 'IF EXISTS'"
-								   " UNION SELECT 'CONCURRENTLY'");
+								   ADDLIST2("", "IF EXISTS","CONCURRENTLY"));
 	else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
-								   " UNION SELECT 'IF EXISTS'");
+								   ADDLIST1("", "IF EXISTS"));
 	/* Try the same after optional words CONCURRENTLY and IF NOT EXISTS */
 	else if (HeadMatches2("DROP", "INDEX") &&
 			 MidMatchAndRemove1(2, "CONCURRENTLY") &&
@@ -2605,14 +2613,14 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("VIEW");
 	else if (Matches2("DROP", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views,
-								   " UNION SELECT 'IF EXISTS'");
+								   ADDLIST1("", "IF EXISTS"));
 	/* Remove optional words IF EXISTS  */
 	else if (HeadMatches2("DROP", "VIEW") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
 			 false) {} /* FALL THROUGH */
 	else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
-								   " UNION SELECT 'IF EXISTS'");
+								   ADDLIST1("", "IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches3("DROP", "MATERIALIZED", "VIEW") &&
 			 MidMatchAndRemove2(3, "IF", "EXISTS") &&
@@ -2630,8 +2638,8 @@ psql_completion(const char *text, int start, int end)
 
 	/* DROP TRIGGER */
 	else if (Matches2("DROP", "TRIGGER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_triggers
-							" UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_list_of_triggers, "IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches2("DROP", "TRIGGER") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -2649,8 +2657,8 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches2("DROP", "EVENT"))
 		COMPLETE_WITH_CONST("TRIGGER");
 	else if (Matches3("DROP", "EVENT", "TRIGGER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers
-							" UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_list_of_event_triggers, "IF EXISTS"));
 	/* Trye the same after removing optional words IF EXISTS */
 	else if (HeadMatches3("DROP", "EVENT", "TRIGGER") &&
 			 MidMatchAndRemove2(3, "IF", "EXISTS") &&
@@ -2659,8 +2667,8 @@ psql_completion(const char *text, int start, int end)
 
 	/* DROP POLICY */
 	else if (Matches2("DROP", "POLICY"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_policies
-							" UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_list_of_policies, "IF EXISTS"));
 	/* Try the same after after removing optional words IF EXISTS */
 	else if (HeadMatches2("DROP", "POLICY") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -2678,8 +2686,8 @@ psql_completion(const char *text, int start, int end)
 
 	/* DROP RULE */
 	else if (Matches2("DROP", "RULE"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_rules
-							"UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_list_of_rules, "IF EXISTS"));
 	/* DROP RULE <name>, after removing optional words IF EXISTS */
 	else if (HeadMatches2("DROP", "RULE") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -2710,8 +2718,8 @@ psql_completion(const char *text, int start, int end)
 			/* Completing USER needs special treat */
 			if (pg_strcasecmp(prev_wd, "USER") == 0)
 			{
-				COMPLETE_WITH_QUERY(Query_for_list_of_roles 
-									"UNION SELECT 'MAPPING' UNION SELECT 'IF EXISTS'");
+				COMPLETE_WITH_QUERY(
+					ADDLIST2(Query_for_list_of_roles, "MAPPING", "IF EXISTS"));
 			}
 			else if (ent->query)
 			{
@@ -2724,7 +2732,7 @@ psql_completion(const char *text, int start, int end)
 			}
 			else if (ent->squery)
 				COMPLETE_WITH_SCHEMA_QUERY(*ent->squery,
-										   " UNION SELECT 'IF EXISTS'");
+										   ADDLIST1("", "IF EXISTS"));
 		}
 	}
 	/* Remove optional IF EXISTS from DROP */
@@ -2795,20 +2803,11 @@ psql_completion(const char *text, int start, int end)
 /* GRANT && REVOKE --- is allowed inside CREATE SCHEMA, so use TailMatches */
 	/* Complete GRANT/REVOKE with a list of roles and privileges */
 	else if (TailMatches1("GRANT|REVOKE"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles
-							" UNION SELECT 'SELECT'"
-							" UNION SELECT 'INSERT'"
-							" UNION SELECT 'UPDATE'"
-							" UNION SELECT 'DELETE'"
-							" UNION SELECT 'TRUNCATE'"
-							" UNION SELECT 'REFERENCES'"
-							" UNION SELECT 'TRIGGER'"
-							" UNION SELECT 'CREATE'"
-							" UNION SELECT 'CONNECT'"
-							" UNION SELECT 'TEMPORARY'"
-							" UNION SELECT 'EXECUTE'"
-							" UNION SELECT 'USAGE'"
-							" UNION SELECT 'ALL'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST13(Query_for_list_of_roles,
+					  "SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE",
+					  "REFERENCES", "TRIGGER", "CREATE", "CONNECT", "TEMPORARY",
+					  "EXECUTE", "USAGE", "ALL"));
 
 	/*
 	 * Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
@@ -2837,21 +2836,22 @@ psql_completion(const char *text, int start, int end)
 	 */
 	else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
-								   " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
-								   " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
-								   " UNION SELECT 'ALL TABLES IN SCHEMA'"
-								   " UNION SELECT 'DATABASE'"
-								   " UNION SELECT 'DOMAIN'"
-								   " UNION SELECT 'FOREIGN DATA WRAPPER'"
-								   " UNION SELECT 'FOREIGN SERVER'"
-								   " UNION SELECT 'FUNCTION'"
-								   " UNION SELECT 'LANGUAGE'"
-								   " UNION SELECT 'LARGE OBJECT'"
-								   " UNION SELECT 'SCHEMA'"
-								   " UNION SELECT 'SEQUENCE'"
-								   " UNION SELECT 'TABLE'"
-								   " UNION SELECT 'TABLESPACE'"
-								   " UNION SELECT 'TYPE'");
+			   ADDLIST15("",
+						 "ALL FUNCTIONS IN SCHEMA",
+						 "ALL SEQUENCES IN SCHEMA",
+						 "ALL TABLES IN SCHEMA",
+						 "DATABASE",
+						 "DOMAIN",
+						 "FOREIGN DATA WRAPPER",
+						 "FOREIGN SERVER",
+						 "FUNCTION",
+						 "LANGUAGE",
+						 "LARGE OBJECT",
+						 "SCHEMA",
+						 "SEQUENCE",
+						 "TABLE",
+						 "TABLESPACE",
+						 "TYPE"));
 
 	else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
 		COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
@@ -2977,7 +2977,7 @@ psql_completion(const char *text, int start, int end)
 	/* Complete LOCK [TABLE] with a list of tables */
 	else if (Matches1("LOCK"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
-								   " UNION SELECT 'TABLE'");
+								   ADDLIST1("", "TABLE"));
 	else if (Matches2("LOCK", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 
@@ -3043,7 +3043,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("VIEW");
 	else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
-								   " UNION SELECT 'CONCURRENTLY'");
+								   ADDLIST1("", "CONCURRENTLY"));
 	else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
 	else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
@@ -3119,7 +3119,8 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST2("ONLY", "WRITE");
 	/* SET CONSTRAINTS */
 	else if (Matches2("SET", "CONSTRAINTS"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema,
+								   ADDLIST1("", "ALL"));
 	/* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
 	else if (Matches3("SET", "CONSTRAINTS", MatchAny))
 		COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
@@ -3131,7 +3132,8 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
 	/* Complete SET SESSION AUTHORIZATION with username */
 	else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST1(Query_for_list_of_roles, "DEFAULT"));
 	/* Complete RESET SESSION with AUTHORIZATION */
 	else if (Matches2("RESET", "SESSION"))
 		COMPLETE_WITH_CONST("AUTHORIZATION");
@@ -3157,10 +3159,11 @@ psql_completion(const char *text, int start, int end)
 			COMPLETE_WITH_LIST(my_list);
 		}
 		else if (TailMatches2("search_path", "TO|="))
-			COMPLETE_WITH_QUERY(Query_for_list_of_schemas
-								" AND nspname not like 'pg\\_toast%%' "
-								" AND nspname not like 'pg\\_temp%%' "
-								" UNION SELECT 'DEFAULT' ");
+			COMPLETE_WITH_QUERY(
+				ADDLIST1(Query_for_list_of_schemas
+						 " AND nspname not like 'pg\\_toast%%' "
+						 " AND nspname not like 'pg\\_temp%%' ",
+						 "DEFAULT"));
 		else
 		{
 			/* generic, type based, GUC support */
@@ -3229,10 +3232,9 @@ psql_completion(const char *text, int start, int end)
 			 MidMatchAndRemove2(3, "IF", "EXISTS") &&
 			 false) {} /* FALL THROUGH */
 	else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles
-							" UNION SELECT 'CURRENT_USER'"
-							" UNION SELECT 'PUBLIC'"
-							" UNION SELECT 'USER'");
+		COMPLETE_WITH_QUERY(
+			ADDLIST3(Query_for_list_of_roles, 
+					 "CURRENT_USER", "PUBLIC", "USER"));
 	else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
 		COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
 	else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
@@ -3246,26 +3248,22 @@ psql_completion(const char *text, int start, int end)
  */
 	else if (Matches1("VACUUM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-								   " UNION SELECT 'FULL'"
-								   " UNION SELECT 'FREEZE'"
-								   " UNION SELECT 'ANALYZE'"
-								   " UNION SELECT 'VERBOSE'");
+		   ADDLIST4("", "FULL", "FREEZE", "ANALYZE", "VERBOSE"));
 	else if (Matches2("VACUUM", "FULL|FREEZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-								   " UNION SELECT 'ANALYZE'"
-								   " UNION SELECT 'VERBOSE'");
+		   ADDLIST2("", "ANALYZE", "VERBOSE"));
 	else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-								   " UNION SELECT 'VERBOSE'");
+		   ADDLIST1("", "VERBOSE"));
 	else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-								   " UNION SELECT 'ANALYZE'");
+		   ADDLIST1("", "ANALYZE"));
 	else if (Matches2("VACUUM", "VERBOSE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-								   " UNION SELECT 'ANALYZE'");
+		   ADDLIST1("", "ANALYZE"));
 	else if (Matches2("VACUUM", "ANALYZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-								   " UNION SELECT 'VERBOSE'");
+		   ADDLIST1("", "VERBOSE"));
 	else if (HeadMatches1("VACUUM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
 
@@ -4030,6 +4028,41 @@ pg_strdup_keyword_case(const char *s, const char *ref)
 	return ret;
 }
 
+/* Construct codelet to append given keywords  */
+static char *
+additional_kw_query(char *prefix, const char *ref, int n, ...)
+{
+	va_list ap;
+	static PQExpBuffer qbuf = NULL;
+	int i;
+
+	if (qbuf == NULL)
+		qbuf = createPQExpBuffer();
+	else
+		resetPQExpBuffer(qbuf);
+
+	appendPQExpBufferStr(qbuf, prefix);
+
+	/* Construct an additional queriy to append keywords */
+	appendPQExpBufferStr(qbuf, " UNION SELECT * FROM (VALUES ");
+
+	va_start(ap, n);
+	for (i = 0 ; i < n ; i++)
+	{
+		char *item = pg_strdup_keyword_case(va_arg(ap, char *), ref);
+		if (i > 0) appendPQExpBufferChar(qbuf, ',');
+		appendPQExpBufferStr(qbuf, "('");
+		appendPQExpBufferStr(qbuf, item);
+		appendPQExpBufferStr(qbuf, "')");
+		pg_free(item);
+	}
+	va_end(ap);
+
+	appendPQExpBufferStr(qbuf, ") as x");
+
+	return qbuf->data;
+}
+
 
 /*
  * escape_string - Escape argument for use as string literal.
-- 
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