agora inbox for [email protected]  
help / color / mirror / Atom feed
From: Kyotaro Horiguchi <[email protected]>
Subject: [PATCH 3/4] Make COMPLETE_WITH_ATTR to accept additional keyword query.
Date: Fri, 1 Apr 2016 17:01:42 +0900

So far the previous commit, COMPLETE_WITH_ATTR cannot accept the new
style of additional keyword list. This patch does the following
things.

1. Change completion_charp from const char * to PQExpBuffer.

2. Chnage COMPLETE_WITH_QUERY and COMPLETE_WITH_ATTR to accept
   an expression instead of string literal.

3. Replace all additional keyword lists in psql_copmletion with
   ADDLISTn() expression.

This leaves keywords contained in Query_for_list_of_grant_roles and
Query_for_enum, but it is the another problem.
---
 src/bin/psql/tab-complete.c | 486 ++++++++++++++++++++++----------------------
 1 file changed, 246 insertions(+), 240 deletions(-)

diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index c530fcb..832bcd7 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -125,7 +125,7 @@ static int	completion_max_records;
  * Communication variables set by COMPLETE_WITH_FOO macros and then used by
  * the completion callback functions.  Ugly but there is no better way.
  */
-static const char *completion_charp;	/* to pass a string */
+static PQExpBuffer completion_charp = NULL;		/* to pass a string */
 static const char *const * completion_charpp;	/* to pass a list of strings */
 static const char *completion_info_charp;		/* to pass a second string */
 static const char *completion_info_charp2;		/* to pass a third string */
@@ -143,16 +143,26 @@ static bool completion_case_sensitive;	/* completion is case sensitive */
  * 5) The list of attributes of the given table (possibly schema-qualified).
  * 6/ The list of arguments to the given function (possibly schema-qualified).
  */
-#define COMPLETE_WITH_QUERY(query) \
+#define APPEND_COMP_CHARP(charp) \
+	appendPQExpBufferStr(completion_charp, charp);
+
+#define SET_COMP_CHARP(charp) \
+	resetPQExpBuffer(completion_charp);	\
+	APPEND_COMP_CHARP(charp);
+
+#define COMPLETION_CHARP (completion_charp->data)
+
+#define COMPLETE_WITH_QUERY(query, addon) \
 do { \
-	completion_charp = query; \
+	SET_COMP_CHARP(query);	\
+	APPEND_COMP_CHARP(addon); \
 	matches = completion_matches(text, complete_from_query); \
 } while (0)
 
 #define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
 do { \
 	completion_squery = &(query); \
-	completion_charp = addon; \
+	SET_COMP_CHARP(addon); \
 	matches = completion_matches(text, complete_from_schema_query); \
 } while (0)
 
@@ -172,7 +182,7 @@ do { \
 
 #define COMPLETE_WITH_CONST(string) \
 do { \
-	completion_charp = string; \
+	SET_COMP_CHARP(string);	\
 	completion_case_sensitive = false; \
 	matches = completion_matches(text, complete_from_const); \
 } while (0)
@@ -190,12 +200,14 @@ do { \
 								false, false, pset.encoding); \
 	if (_completion_table == NULL) \
 	{ \
-		completion_charp = Query_for_list_of_attributes  addon; \
+		SET_COMP_CHARP(Query_for_list_of_attributes); \
+		APPEND_COMP_CHARP(addon);					  \
 		completion_info_charp = relation; \
 	} \
 	else \
 	{ \
-		completion_charp = Query_for_list_of_attributes_with_schema  addon; \
+		SET_COMP_CHARP(Query_for_list_of_attributes_with_schema); \
+		APPEND_COMP_CHARP(addon); \
 		completion_info_charp = _completion_table; \
 		completion_info_charp2 = _completion_schema; \
 	} \
@@ -215,12 +227,12 @@ do { \
 								   false, false, pset.encoding); \
 	if (_completion_function == NULL) \
 	{ \
-		completion_charp = Query_for_list_of_arguments; \
+		SET_COMP_CHARP(Query_for_list_of_arguments); \
 		completion_info_charp = function; \
 	} \
 	else \
 	{ \
-		completion_charp = Query_for_list_of_arguments_with_schema; \
+		SET_COMP_CHARP(Query_for_list_of_arguments_with_schema); \
 		completion_info_charp = _completion_function; \
 		completion_info_charp2 = _completion_schema; \
 	} \
@@ -312,16 +324,16 @@ 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,		\
+#define ADDLIST1(s1) additional_kw_query(text, 1, s1)
+#define ADDLIST2(s1, s2) additional_kw_query(text, 2, s1, s2)
+#define ADDLIST3(s1, s2, s3) additional_kw_query(text, 3, s1, s2, s3)
+#define ADDLIST4(s1, s2, s3, s4) \
+	additional_kw_query(text, 4, s1, s2, s3, s4)
+#define ADDLIST13(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13) \
+	additional_kw_query(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,		\
+#define ADDLIST15(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15) \
+	additional_kw_query(text, 12, s1, s2, s3, s4, s5, s6, s7,		\
 						s8, s9, s10, s11, s12, s13, s14, s15)
 
 /*
@@ -975,7 +987,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 *additional_kw_query( const char *ref, int n, ...);
 static char *escape_string(const char *text);
 static PGresult *exec_query(const char *query);
 
@@ -1406,7 +1418,8 @@ psql_completion(const char *text, int start, int end)
 #endif
 
 	/* Clear a few things. */
-	completion_charp = NULL;
+	if (completion_charp == NULL)
+		completion_charp = createPQExpBuffer();
 	completion_charpp = NULL;
 	completion_info_charp = NULL;
 	completion_info_charp2 = NULL;
@@ -1461,13 +1474,13 @@ 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,
-			ADDLIST2("", "IF EXISTS", "ALL IN TABLESPACE"));
+			ADDLIST2("IF EXISTS", "ALL IN TABLESPACE"));
 
 	/* ALTER TABLE after removing optional words IF EXISTS*/
 	else if (HeadMatches2("ALTER", "TABLE") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
 			 Matches2("ALTER", "TABLE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 
 	/* ALTER something */
 	else if (Matches1("ALTER"))
@@ -1487,7 +1500,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
 	/* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
 	else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 	/* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
 	else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
 		COMPLETE_WITH_CONST("SET TABLESPACE");
@@ -1523,7 +1536,7 @@ psql_completion(const char *text, int start, int end)
 
 	/* ALTER EVENT TRIGGER */
 	else if (Matches3("ALTER", "EVENT", "TRIGGER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
+		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers, "");
 
 	/* ALTER EVENT TRIGGER <name> */
 	else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
@@ -1541,14 +1554,14 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
+		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO,"");
 	}
 
 	/* ALTER EXTENSION <name> UPDATE TO */
 	else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
+		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions, "");
 	}
 
 	/* ALTER FOREIGN */
@@ -1562,13 +1575,13 @@ 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,
-								   ADDLIST1("", "IF EXISTS"));
+								   ADDLIST1("IF EXISTS"));
 
 	/* ALTER|DROP FOREIGN TABLE after removing optinal words IF EXISTS */
 	else if (HeadMatches3("ALTER|DROP", "FOREIGN", "TABLE") &&
 			 MidMatchAndRemove2(3, "IF", "EXISTS") &&
 			 Matches3("ALTER|DROP", "FOREIGN", "TABLE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, "");
 
 	/* ALTER FOREIGN TABLE <name> */
 	else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
@@ -1583,17 +1596,17 @@ psql_completion(const char *text, int start, int end)
 
 	/* ALTER FOREIGN TABLE xxx RENAME */
 	else if (Matches5("ALTER", "FOREIGN", "TABLE", MatchAny, "RENAME"))
-		COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'TO'");
+		COMPLETE_WITH_ATTR(prev2_wd, ADDLIST2("COLUMN", "TO"));
 
 	/* ALTER INDEX */
 	else if (Matches2("ALTER", "INDEX"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
-			   ADDLIST2("", "IF EXISTS", "ALL IN TABLESPACE"));
+			   ADDLIST2("IF EXISTS", "ALL IN TABLESPACE"));
 	/* ALTER INDEX after removing optional words IF EXISTS */
 	else if (HeadMatches2("ALTER", "INDEX") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
 			 Matches2("ALTER", "INDEX"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, "");
 
 	/* ALTER INDEX <name> */
 	else if (Matches3("ALTER", "INDEX", MatchAny))
@@ -1623,13 +1636,13 @@ 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,
-			   ADDLIST2("", "IF EXISTS", "ALL IN TABLESPACE"));
+			   ADDLIST2("IF EXISTS", "ALL IN TABLESPACE"));
 
 	/* ALTER MATERIALIZED VIEW with name after removing optional words */
 	else if (HeadMatches3("ALTER", "MATERIALIZED", "VIEW") &&
 			 MidMatchAndRemove2(3, "IF", "EXISTS") &&
 			 Matches3("ALTER", "MATERIALIZED", "VIEW"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, "");
 
 	/* ALTER USER,ROLE <name> */
 	else if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
@@ -1685,14 +1698,14 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches5("ALTER", "DOMAIN", MatchAny, "RENAME|VALIDATE", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
+		COMPLETE_WITH_QUERY(Query_for_constraint_of_type, "");
 	}
 	/* ALTER DOMAIN <sth> DROP CONSTRAINT */
 	else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(
-			ADDLIST1(Query_for_constraint_of_type, "IF EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_constraint_of_type,
+							ADDLIST1("IF EXISTS"));
 	}
 	/* Try the same match after removing optional words IF EXISTS */
 	else if (HeadMatches5("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT") &&
@@ -1700,7 +1713,7 @@ psql_completion(const char *text, int start, int end)
 			 Matches5("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
+		COMPLETE_WITH_QUERY(Query_for_constraint_of_type, "");
 	}
 	/* ALTER DOMAIN <sth> RENAME */
 	else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
@@ -1714,7 +1727,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,
-								   ADDLIST1("", "IF EXISTS"));
+								   ADDLIST1("IF EXISTS"));
 	/* ALTER SEQUENCE with name after removing optional words IF EXISTS */
 	else if (HeadMatches2("ALTER", "SEQUENCE") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -1740,11 +1753,11 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST2("SET", "RESET");
 	/* ALTER SYSTEM SET|RESET <name> */
 	else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
+		COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars, "");
 	/* ALTER VIEW */
 	else if (Matches2("ALTER", "VIEW"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views,
-								   ADDLIST1("", "IF EXISTS"));
+								   ADDLIST1("IF EXISTS"));
 	/* ALTER VIEW <name> with subcommands after removing optional worlds */
 	else if (HeadMatches2("ALTER", "VIEW") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -1758,8 +1771,8 @@ psql_completion(const char *text, int start, int end)
 
 	/* ALTER POLICY */
 	else if (Matches2("ALTER", "POLICY"))
-		COMPLETE_WITH_QUERY(
-			ADDLIST1(Query_for_list_of_policies, "IF EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_policies,
+							ADDLIST1("IF EXISTS"));
 	/* ALTER POLICY <name> with ON after removing optional words IF EXISTS */
 	else if (HeadMatches2("ALTER", "POLICY") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -1769,14 +1782,14 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy, "");
 	}
 	/* ALTER POLICY <name> ON <table> - show options */
 	else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
 	/* ALTER POLICY <name> ON <table> TO <role> */
 	else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles, "");
 	/* ALTER POLICY <name> ON <table> USING ( */
 	else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
 		COMPLETE_WITH_CONST("(");
@@ -1792,7 +1805,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule, "");
 	}
 
 	/* ALTER RULE <name> ON <name> */
@@ -1806,14 +1819,14 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger, "");
 	}
 
 	/*
 	 * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
 	 */
 	else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 
 	/* ALTER TRIGGER <name> ON <name> */
 	else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
@@ -1840,22 +1853,22 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_rule_of_table);
+		COMPLETE_WITH_QUERY(Query_for_rule_of_table, "");
 	}
 	else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
 	{
 		completion_info_charp = prev4_wd;
-		COMPLETE_WITH_QUERY(Query_for_rule_of_table);
+		COMPLETE_WITH_QUERY(Query_for_rule_of_table, "");
 	}
 	else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
+		COMPLETE_WITH_QUERY(Query_for_trigger_of_table, "");
 	}
 	else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
 	{
 		completion_info_charp = prev4_wd;
-		COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
+		COMPLETE_WITH_QUERY(Query_for_trigger_of_table, "");
 	}
 	/* ALTER TABLE xxx INHERIT */
 	else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
@@ -1869,21 +1882,21 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_rule_of_table);
+		COMPLETE_WITH_QUERY(Query_for_rule_of_table, "");
 	}
 	else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
+		COMPLETE_WITH_QUERY(Query_for_trigger_of_table, "");
 	}
 
 	/* ALTER TABLE xxx ALTER */
 	else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
-		COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
+		COMPLETE_WITH_ATTR(prev2_wd, ADDLIST2("COLUMN", "CONSTRAINT"));
 
 	/* ALTER TABLE xxx RENAME */
 	else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
-		COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
+		COMPLETE_WITH_ATTR(prev2_wd, ADDLIST3("COLUMN", "CONSTRAINT", "TO"));
 	else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
 		COMPLETE_WITH_ATTR(prev3_wd, "");
 
@@ -1902,7 +1915,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
 	/*  ALTER TABLE DROP COLUMN may take IF EXISTS */
 	else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
-		COMPLETE_WITH_ATTR(prev3_wd, "UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_ATTR(prev3_wd, ADDLIST1("IF EXISTS"));
 	/* ALTER TABLE <name> with ADD/ALTER/DROP after removing optional words */
 	else if (HeadMatches4("ALTER", "TABLE", MatchAny, "ADD|ALTER|DROP") &&
 			 MidMatchAndRemove1(4, "COLUMN") &&
@@ -1911,7 +1924,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_ATTR(prev2_wd, "");
 	/* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
 	else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
-		COMPLETE_WITH_ATTR(prev3_wd, "UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_ATTR(prev3_wd, ADDLIST1("IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN") &&
 			 MidMatchAndRemove2(5, "IF", "EXISTS") &&
@@ -1925,7 +1938,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME|VALIDATE", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
+		COMPLETE_WITH_QUERY(Query_for_constraint_of_table, "");
 	}
 	/*
 	 * If we have ALTER TABLE <sth> DROP CONSTRAINT,
@@ -1934,8 +1947,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(
-			ADDLIST1(Query_for_constraint_of_table, "IF EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_constraint_of_table,
+							ADDLIST1("IF EXISTS"));
 	}
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches5("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT") &&
@@ -1943,7 +1956,7 @@ psql_completion(const char *text, int start, int end)
 			 Matches5("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
+		COMPLETE_WITH_QUERY(Query_for_constraint_of_table, "");
 	}
 	/* ALTER TABLE ALTER [COLUMN] <foo> */
 	else if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
@@ -1970,7 +1983,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
 	{
 		completion_info_charp = prev3_wd;
-		COMPLETE_WITH_QUERY(Query_for_index_of_table);
+		COMPLETE_WITH_QUERY(Query_for_index_of_table, "");
 	}
 	/* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
 	else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
@@ -1982,7 +1995,7 @@ psql_completion(const char *text, int start, int end)
 	 * tablespaces
 	 */
 	else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces, "");
 	/* If we have ALTER TABLE <sth> SET WITH provide OIDS */
 	else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
 		COMPLETE_WITH_CONST("OIDS");
@@ -2034,7 +2047,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
 	{
 		completion_info_charp = prev5_wd;
-		COMPLETE_WITH_QUERY(Query_for_index_of_table);
+		COMPLETE_WITH_QUERY(Query_for_index_of_table, "");
 	}
 	else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
 		COMPLETE_WITH_CONST("INDEX");
@@ -2099,7 +2112,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|RENAME", "ATTRIBUTE"))
 		COMPLETE_WITH_ATTR(prev3_wd, "");
 	else if (Matches5("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE"))
-		COMPLETE_WITH_ATTR(prev3_wd, " UNION SELECT 'IF EXISTS'");
+		COMPLETE_WITH_ATTR(prev3_wd, ADDLIST1("IF EXISTS"));
 	/* Remove optional words IF EXISTS */
 	else if (HeadMatches5("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE") &&
 			 MidMatchAndRemove2(5, "IF", "EXISTS") &&
@@ -2114,7 +2127,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("USER");
 	/* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
 	else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 
 /* BEGIN */
 	else if (Matches1("BEGIN"))
@@ -2134,9 +2147,9 @@ psql_completion(const char *text, int start, int end)
 /* CLUSTER */
 	else if (Matches1("CLUSTER"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-								   ADDLIST1("", "VERBOSE"));
+								   ADDLIST1("VERBOSE"));
 	else if (Matches2("CLUSTER", "VERBOSE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "");
 	/* If we have CLUSTER <sth>, then add "USING" */
 	else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
 		COMPLETE_WITH_CONST("USING");
@@ -2148,7 +2161,7 @@ psql_completion(const char *text, int start, int end)
 			 Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_index_of_table);
+		COMPLETE_WITH_QUERY(Query_for_index_of_table, "");
 	}
 
 /* COMMENT */
@@ -2168,24 +2181,24 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST(list_COMMENT);
 	}
 	else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
+		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods, "");
 	else if (Matches3("COMMENT", "ON", "FOREIGN"))
 		COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
 	else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
 		COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
 	else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
-		COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
+		COMPLETE_WITH_QUERY(Query_for_all_table_constraints, "");
 	else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
 		COMPLETE_WITH_CONST("ON");
 	else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint, "");
 	}
 	else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, "");
 	else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
+		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers, "");
 	else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
 		Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
 			 Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
@@ -2199,10 +2212,10 @@ psql_completion(const char *text, int start, int end)
 	 */
 	else if (Matches1("COPY|\\copy"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
-								   ADDLIST1("", "("));
+								   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);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 	/* If we have COPY (, complete it with legal commands */
 	else if (Matches2("COPY|\\copy", "("))
 		COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
@@ -2214,7 +2227,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
 			 Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
 	{
-		completion_charp = "";
+		SET_COMP_CHARP("");
 		matches = completion_matches(text, complete_from_files);
 	}
 
@@ -2249,18 +2262,18 @@ psql_completion(const char *text, int start, int end)
 							"LC_COLLATE", "LC_CTYPE");
 
 	else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
+		COMPLETE_WITH_QUERY(Query_for_list_of_template_databases, "");
 
 	/* CREATE EXTENSION */
 	/* Complete with available extensions rather than installed ones. */
 	else if (Matches2("CREATE", "EXTENSION"))
-		COMPLETE_WITH_QUERY(ADDLIST1(Query_for_list_of_available_extensions,
-									 "IF NOT EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions,
+							ADDLIST1("IF NOT EXISTS"));
 	/* Try the same after removing optional words IF NOT EXISTS */
 	else if (HeadMatches2("CREATE", "EXTENSION") &&
 			 MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") &&
 			 Matches2("CREATE", "EXTENSION"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
+		COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions, "");
 	/* CREATE EXTENSION <name> */
 	else if (Matches3("CREATE", "EXTENSION", MatchAny))
 		COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
@@ -2268,7 +2281,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
+		COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions, "");
 	}
 
 	/* CREATE FOREIGN */
@@ -2278,7 +2291,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,
-								   ADDLIST1("", "IF NOT EXISTS"));
+								   ADDLIST1("IF NOT EXISTS"));
 	/* Remove optional words IF NOT EXISTS */
 	else if (HeadMatches3("CREATE", "FOREIGN", "TABLE") &&
 			 MidMatchAndRemove3(3, "IF", "NOT", "EXISTS") &&
@@ -2300,12 +2313,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,
-				   ADDLIST3("", "ON", "CONCURRENTLY", "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,
-								   ADDLIST2("", "IF NOT EXISTS", "ON"));
+								   ADDLIST2("IF NOT EXISTS", "ON"));
 
 	/* Remove optional words "CONCURRENTLY",  "IF NOT EXISTS" */
 	else if (HeadMatches2("CREATE", "INDEX") &&
@@ -2316,7 +2329,7 @@ psql_completion(const char *text, int start, int end)
 	/* Complete CREATE INDEX [<name>] ON with a list of tables */
 	else if (Matches4("CREATE", "INDEX", MatchAny, "ON") ||
 			 Matches3("CREATE", "INDEX", "ON"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "");
 
 	/* Complete CREATE INDEX <sth> with "ON" */
 	else if (Matches3("CREATE", "INDEX", MatchAny))
@@ -2338,7 +2351,7 @@ psql_completion(const char *text, int start, int end)
 	/* Complete USING with an index method */
 	else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
 			 TailMatches4("INDEX", "ON", MatchAny, "USING"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
+		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))
@@ -2350,7 +2363,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("ON");
 	/* Complete "CREATE POLICY <name> ON <table>" */
 	else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 	/* Complete "CREATE POLICY <name> ON <table> FOR|TO|USING|WITH CHECK" */
 	else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST4("FOR", "TO", "USING (", "WITH CHECK (");
@@ -2368,7 +2381,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
 	/* Complete "CREATE POLICY <name> ON <table> TO <role>" */
 	else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles, "");
 	/* Complete "CREATE POLICY <name> ON <table> USING (" */
 	else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
 		COMPLETE_WITH_CONST("(");
@@ -2388,7 +2401,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("TO");
 	/* Complete "AS ON <sth> TO" with a table name */
 	else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 
 /* Remove optional words TEMPORARY/TEMP */
 	else if (HeadMatches3("CREATE", MatchAny, "SEQUENCE") &&
@@ -2397,7 +2410,7 @@ psql_completion(const char *text, int start, int end)
 /* CREATE SEQUENCE */
 	else if(Matches2("CREATE", "SEQUENCE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences,
-								   ADDLIST1("", "IF NOT EXISTS"));
+								   ADDLIST1("IF NOT EXISTS"));
 	else if(HeadMatches2("CREATE", "SEQUENCE") &&
 			MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") &&
 			Matches3("CREATE", "SEQUENCE", MatchAny))
@@ -2412,8 +2425,8 @@ psql_completion(const char *text, int start, int end)
 
 /* CREATE SCHEMA <name> */
 	else if (Matches2("CREATE", "SCHEMA"))
-		COMPLETE_WITH_QUERY(
-			ADDLIST1(Query_for_list_of_schemas, "IF NOT EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_schemas,
+							ADDLIST1("IF NOT EXISTS"));
 	/* Remove optional words IF NOT EXISTS */
 	else if (HeadMatches2("CREATE", "SCHEMA") &&
 			 MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") &&
@@ -2433,7 +2446,7 @@ psql_completion(const char *text, int start, int end)
 			 false) {} /* FALL THROUGH*/
 	else if (Matches2("CREATE", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
-								   ADDLIST1("", "IF NOT EXISTS"));
+								   ADDLIST1("IF NOT EXISTS"));
 
 	/* Remove optional words here */
 	else if (HeadMatches2("CREATE", "TABLE") &&
@@ -2473,10 +2486,10 @@ psql_completion(const char *text, int start, int end)
 	 * tables
 	 */
 	else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 	/* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
 	else if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, "");
 	/* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
 	else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
 		COMPLETE_WITH_CONST("PROCEDURE");
@@ -2524,7 +2537,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,
-								   ADDLIST1("", "IF NOT EXISTS"));
+								   ADDLIST1("IF NOT EXISTS"));
 	/* CREATE VIEW <name> with AS after removing optional words */
 	else if (HeadMatches2("CREATE", "VIEW") &&
 			 MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") &&
@@ -2539,13 +2552,13 @@ 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,
-								   ADDLIST1("", "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") &&
 			 MidMatchAndRemove3(3, "IF", "NOT", "EXISTS") &&
 			 Matches3("CREATE", "MATERIALIZED", "VIEW"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, "");
 	/* Complete CREATE MATERIALIZED VIEW <name> with AS */
 	else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
 		COMPLETE_WITH_CONST("AS");
@@ -2576,7 +2589,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("FROM");
 	/* Complete DELETE FROM with a list of tables */
 	else if (TailMatches2("DELETE", "FROM"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, "");
 	/* Complete DELETE FROM <table> */
 	else if (TailMatches3("DELETE", "FROM", MatchAny))
 		COMPLETE_WITH_LIST2("USING", "WHERE");
@@ -2607,10 +2620,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,
-								   ADDLIST1("", "IF EXISTS"));
+								   ADDLIST1("IF EXISTS"));
 	else if (Matches2("DROP", "FUNCTION"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions,
-								   ADDLIST1("", "IF EXISTS"));
+								   ADDLIST1("IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches2("DROP", "AGGREGATE|FUNCTION") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -2621,8 +2634,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(
-			ADDLIST1(Query_for_list_of_fdws, "IF EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_fdws,
+							ADDLIST1("IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches4("DROP", "FOREIGN", "DATA", "WRAPPER") &&
 			 MidMatchAndRemove2(4, "IF", "EXISTS") &&
@@ -2631,10 +2644,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,
-								   ADDLIST2("", "IF EXISTS","CONCURRENTLY"));
+								   ADDLIST2("IF EXISTS","CONCURRENTLY"));
 	else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
-								   ADDLIST1("", "IF EXISTS"));
+								   ADDLIST1("IF EXISTS"));
 	/* Try the same after optional words CONCURRENTLY and IF NOT EXISTS */
 	else if (HeadMatches2("DROP", "INDEX") &&
 			 MidMatchAndRemove1(2, "CONCURRENTLY") &&
@@ -2647,33 +2660,33 @@ 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,
-								   ADDLIST1("", "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,
-								   ADDLIST1("", "IF EXISTS"));
+								   ADDLIST1("IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches3("DROP", "MATERIALIZED", "VIEW") &&
 			 MidMatchAndRemove2(3, "IF", "EXISTS") &&
 			 Matches3("DROP", "MATERIALIZED", "VIEW"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, "");
 
 	/* DROP OWNED BY */
 	else if (Matches2("DROP", "OWNED"))
 		COMPLETE_WITH_CONST("BY");
 	else if (Matches3("DROP", "OWNED", "BY"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 
 	else if (Matches3("DROP", "TEXT", "SEARCH"))
 		COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
 
 	/* DROP TRIGGER */
 	else if (Matches2("DROP", "TRIGGER"))
-		COMPLETE_WITH_QUERY(
-			ADDLIST1(Query_for_list_of_triggers, "IF EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_triggers,
+							ADDLIST1("IF EXISTS"));
 	/* Try the same after removing optional words IF EXISTS */
 	else if (HeadMatches2("DROP", "TRIGGER") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -2682,7 +2695,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger, "");
 	}
 	else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
@@ -2691,29 +2704,29 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches2("DROP", "ACCESS"))
 		COMPLETE_WITH_CONST("METHOD");
 	else if (Matches3("DROP", "ACCESS", "METHOD"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
+		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods, "");
 
 	/* DROP EVENT TRIGGER */
 	else if (Matches2("DROP", "EVENT"))
 		COMPLETE_WITH_CONST("TRIGGER");
 	else if (Matches3("DROP", "EVENT", "TRIGGER"))
-		COMPLETE_WITH_QUERY(
-			ADDLIST1(Query_for_list_of_event_triggers, "IF EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers,
+							ADDLIST1("IF EXISTS"));
 	/* Trye the same after removing optional words IF EXISTS */
 	else if (HeadMatches3("DROP", "EVENT", "TRIGGER") &&
 			 MidMatchAndRemove2(3, "IF", "EXISTS") &&
 			 Matches3("DROP", "EVENT", "TRIGGER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
+		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers, "");
 
 	/* DROP POLICY */
 	else if (Matches2("DROP", "POLICY"))
-		COMPLETE_WITH_QUERY(
-			ADDLIST1(Query_for_list_of_policies, "IF EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_policies,
+							ADDLIST1("IF EXISTS"));
 	/* Try the same after after removing optional words IF EXISTS */
 	else if (HeadMatches2("DROP", "POLICY") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
 			 Matches2("DROP", "POLICY"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_policies);
+		COMPLETE_WITH_QUERY(Query_for_list_of_policies, "");
 	/* DROP POLICY <name> */
 	else if (Matches3("DROP", "POLICY", MatchAny))
 		COMPLETE_WITH_CONST("ON");
@@ -2721,13 +2734,13 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy, "");
 	}
 
 	/* DROP RULE */
 	else if (Matches2("DROP", "RULE"))
-		COMPLETE_WITH_QUERY(
-			ADDLIST1(Query_for_list_of_rules, "IF EXISTS"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_rules,
+							ADDLIST1("IF EXISTS"));
 	/* DROP RULE <name>, after removing optional words IF EXISTS */
 	else if (HeadMatches2("DROP", "RULE") &&
 			 MidMatchAndRemove2(2, "IF", "EXISTS") &&
@@ -2736,7 +2749,7 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches4("DROP", "RULE", MatchAny, "ON"))
 	{
 		completion_info_charp = prev2_wd;
-		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule, "");
 	}
 	else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
 		COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
@@ -2751,15 +2764,15 @@ psql_completion(const char *text, int start, int end)
 
 	{
 		const pgsql_thing_t *ent = find_thing_entry(prev_wd);
-		char *addition = ADDLIST1("", "IF EXISTS");
+		char *addition = ADDLIST1("IF EXISTS");
 
 		if (ent)
 		{
 			/* Completing USER needs special treat */
 			if (pg_strcasecmp(prev_wd, "USER") == 0)
 			{
-				COMPLETE_WITH_QUERY(
-					ADDLIST2(Query_for_list_of_roles, "MAPPING", "IF EXISTS"));
+				COMPLETE_WITH_QUERY(Query_for_list_of_roles,
+									ADDLIST2("MAPPING", "IF EXISTS"));
 			}
 			else if (ent->query)
 			{
@@ -2767,12 +2780,12 @@ psql_completion(const char *text, int start, int end)
 									  strlen(addition) + 1);
 				strcpy(buf, ent->query);
 				strcat(buf, addition);
-				COMPLETE_WITH_QUERY(buf);
+				COMPLETE_WITH_QUERY(buf, "");
 				free(buf);
 			}
 			else if (ent->squery)
 				COMPLETE_WITH_SCHEMA_QUERY(*ent->squery,
-										   ADDLIST1("", "IF EXISTS"));
+										   ADDLIST1("IF EXISTS"));
 		}
 	}
 	/* Remove optional IF EXISTS from DROP */
@@ -2789,7 +2802,7 @@ psql_completion(const char *text, int start, int end)
 
 /* EXECUTE */
 	else if (Matches1("EXECUTE"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
+		COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements, "");
 
 /* EXPLAIN */
 
@@ -2826,7 +2839,7 @@ psql_completion(const char *text, int start, int end)
 	/* applies in ALTER/DROP FDW and in CREATE SERVER */
 	else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
 			 !TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
-		COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
+		COMPLETE_WITH_QUERY(Query_for_list_of_fdws, "");
 	/* applies in CREATE SERVER */
 	else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
 			 HeadMatches2("CREATE", "SERVER"))
@@ -2834,18 +2847,17 @@ psql_completion(const char *text, int start, int end)
 
 /* FOREIGN TABLE */
 	else if (TailMatches2("FOREIGN", "TABLE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, "");
 
 /* FOREIGN SERVER */
 	else if (TailMatches2("FOREIGN", "SERVER"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_servers);
+		COMPLETE_WITH_QUERY(Query_for_list_of_servers, "");
 
 /* 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(
-			ADDLIST13(Query_for_list_of_roles,
-					  "SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE",
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles,
+			ADDLIST13("SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE",
 					  "REFERENCES", "TRIGGER", "CREATE", "CONNECT", "TEMPORARY",
 					  "EXECUTE", "USAGE", "ALL"));
 
@@ -2876,8 +2888,7 @@ 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,
-			   ADDLIST15("",
-						 "ALL FUNCTIONS IN SCHEMA",
+			   ADDLIST15("ALL FUNCTIONS IN SCHEMA",
 						 "ALL SEQUENCES IN SCHEMA",
 						 "ALL TABLES IN SCHEMA",
 						 "DATABASE",
@@ -2909,23 +2920,23 @@ psql_completion(const char *text, int start, int end)
 	else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
 	{
 		if (TailMatches1("DATABASE"))
-			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
+			COMPLETE_WITH_QUERY(Query_for_list_of_databases, "");
 		else if (TailMatches1("DOMAIN"))
-			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, "");
 		else if (TailMatches1("FUNCTION"))
-			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, "");
 		else if (TailMatches1("LANGUAGE"))
-			COMPLETE_WITH_QUERY(Query_for_list_of_languages);
+			COMPLETE_WITH_QUERY(Query_for_list_of_languages, "");
 		else if (TailMatches1("SCHEMA"))
-			COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
+			COMPLETE_WITH_QUERY(Query_for_list_of_schemas, "");
 		else if (TailMatches1("SEQUENCE"))
-			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, "");
 		else if (TailMatches1("TABLE"))
-			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, "");
 		else if (TailMatches1("TABLESPACE"))
-			COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
+			COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces, "");
 		else if (TailMatches1("TYPE"))
-			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
+			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, "");
 		else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
 			COMPLETE_WITH_CONST("TO");
 		else
@@ -2938,7 +2949,7 @@ psql_completion(const char *text, int start, int end)
 	 */
 	else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
 			 (HeadMatches1("REVOKE") && TailMatches1("FROM")))
-		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles, "");
 
 	/* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
 	else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
@@ -2989,7 +3000,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("INTO");
 	/* Complete INSERT INTO with table names */
 	else if (TailMatches2("INSERT", "INTO"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, "");
 	/* Complete "INSERT INTO <table> (" with attribute names */
 	else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
 		COMPLETE_WITH_ATTR(prev2_wd, "");
@@ -3017,7 +3028,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,
-								   ADDLIST1("", "TABLE"));
+								   ADDLIST1("TABLE"));
 	else if (Matches2("LOCK", "TABLE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 
@@ -3039,7 +3050,7 @@ psql_completion(const char *text, int start, int end)
 
 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
 	else if (TailMatches1("NOTIFY"))
-		COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s'");
+		COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s'", "");
 
 /* OPTIONS */
 	else if (TailMatches1("OPTIONS"))
@@ -3047,7 +3058,7 @@ psql_completion(const char *text, int start, int end)
 
 /* OWNER TO  - complete with available roles */
 	else if (TailMatches2("OWNER", "TO"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 
 /* ORDER BY */
 	else if (TailMatches3("FROM", MatchAny, "ORDER"))
@@ -3070,11 +3081,11 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches2("REASSIGN", "OWNED"))
 		COMPLETE_WITH_CONST("BY");
 	else if (Matches3("REASSIGN", "OWNED", "BY"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 	else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
 		COMPLETE_WITH_CONST("TO");
 	else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 
 /* REFRESH MATERIALIZED VIEW */
 	else if (Matches1("REFRESH"))
@@ -3083,9 +3094,9 @@ 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,
-								   ADDLIST1("", "CONCURRENTLY"));
+								   ADDLIST1("CONCURRENTLY"));
 	else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, "");
 	else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
 		COMPLETE_WITH_CONST("WITH");
 	else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
@@ -3103,13 +3114,13 @@ psql_completion(const char *text, int start, int end)
 	else if (Matches1("REINDEX"))
 		COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
 	else if (Matches2("REINDEX", "TABLE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "");
 	else if (Matches2("REINDEX", "INDEX"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, "");
 	else if (Matches2("REINDEX", "SCHEMA"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
+		COMPLETE_WITH_QUERY(Query_for_list_of_schemas, "");
 	else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_databases);
+		COMPLETE_WITH_QUERY(Query_for_list_of_databases, "");
 
 /* SECURITY LABEL */
 	else if (Matches1("SECURITY"))
@@ -3138,9 +3149,9 @@ psql_completion(const char *text, int start, int end)
 /* SET, RESET, SHOW */
 	/* Complete with a variable name */
 	else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
+		COMPLETE_WITH_QUERY(Query_for_list_of_set_vars, "");
 	else if (Matches1("SHOW"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
+		COMPLETE_WITH_QUERY(Query_for_list_of_show_vars, "");
 	/* Complete "SET TRANSACTION" */
 	else if (Matches2("SET", "TRANSACTION"))
 		COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
@@ -3176,20 +3187,20 @@ psql_completion(const char *text, int start, int end)
 	/* SET CONSTRAINTS */
 	else if (Matches2("SET", "CONSTRAINTS"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema,
-								   ADDLIST1("", "ALL"));
+								   ADDLIST1("ALL"));
 	/* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
 	else if (Matches3("SET", "CONSTRAINTS", MatchAny))
 		COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
 	/* Complete SET ROLE */
 	else if (Matches2("SET", "ROLE"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 	/* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
 	else if (Matches2("SET", "SESSION"))
 		COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
 	/* Complete SET SESSION AUTHORIZATION with username */
 	else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
-		COMPLETE_WITH_QUERY(
-			ADDLIST1(Query_for_list_of_roles, "DEFAULT"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles,
+							ADDLIST1("DEFAULT"));
 	/* Complete RESET SESSION with AUTHORIZATION */
 	else if (Matches2("RESET", "SESSION"))
 		COMPLETE_WITH_CONST("AUTHORIZATION");
@@ -3215,11 +3226,10 @@ psql_completion(const char *text, int start, int end)
 			COMPLETE_WITH_LIST(my_list);
 		}
 		else if (TailMatches2("search_path", "TO|="))
-			COMPLETE_WITH_QUERY(
-				ADDLIST1(Query_for_list_of_schemas
-						 " AND nspname not like 'pg\\_toast%%' "
-						 " AND nspname not like 'pg\\_temp%%' ",
-						 "DEFAULT"));
+			COMPLETE_WITH_QUERY(Query_for_list_of_schemas
+								" AND nspname not like 'pg\\_toast%%' "
+								" AND nspname not like 'pg\\_temp%%' ",
+								ADDLIST1("DEFAULT"));
 		else
 		{
 			/* generic, type based, GUC support */
@@ -3230,7 +3240,7 @@ psql_completion(const char *text, int start, int end)
 				char		querybuf[1024];
 
 				snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
-				COMPLETE_WITH_QUERY(querybuf);
+				COMPLETE_WITH_QUERY(querybuf, "");
 			}
 			else if (guctype && strcmp(guctype, "bool") == 0)
 				COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
@@ -3249,26 +3259,26 @@ psql_completion(const char *text, int start, int end)
 
 /* TABLE, but not TABLE embedded in other commands */
 	else if (Matches1("TABLE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, "");
 
 /* TABLESAMPLE */
 	else if (TailMatches1("TABLESAMPLE"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods, "");
 	else if (TailMatches2("TABLESAMPLE", MatchAny))
 		COMPLETE_WITH_CONST("(");
 
 /* TRUNCATE */
 	else if (Matches1("TRUNCATE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 
 /* UNLISTEN */
 	else if (Matches1("UNLISTEN"))
-		COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s' UNION SELECT '*'");
+		COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s' UNION SELECT '*'", "");
 
 /* UPDATE --- can be inside EXPLAIN, RULE, etc */
 	/* If prev. word is UPDATE suggest a list of tables */
 	else if (TailMatches1("UPDATE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, "");
 	/* Complete UPDATE <table> with "SET" */
 	else if (TailMatches2("UPDATE", MatchAny))
 		COMPLETE_WITH_CONST("SET");
@@ -3288,11 +3298,10 @@ 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(
-			ADDLIST3(Query_for_list_of_roles, 
-					 "CURRENT_USER", "PUBLIC", "USER"));
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles,
+							ADDLIST3("CURRENT_USER", "PUBLIC", "USER"));
 	else if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
+		COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings, "");
 	else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
 		COMPLETE_WITH_CONST("SERVER");
 	else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
@@ -3304,24 +3313,24 @@ psql_completion(const char *text, int start, int end)
  */
 	else if (Matches1("VACUUM"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-		   ADDLIST4("", "FULL", "FREEZE", "ANALYZE", "VERBOSE"));
+		   ADDLIST4("FULL", "FREEZE", "ANALYZE", "VERBOSE"));
 	else if (Matches2("VACUUM", "FULL|FREEZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-		   ADDLIST2("", "ANALYZE", "VERBOSE"));
+		   ADDLIST2("ANALYZE", "VERBOSE"));
 	else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-		   ADDLIST1("", "VERBOSE"));
+		   ADDLIST1("VERBOSE"));
 	else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-		   ADDLIST1("", "ANALYZE"));
+		   ADDLIST1("ANALYZE"));
 	else if (Matches2("VACUUM", "VERBOSE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-		   ADDLIST1("", "ANALYZE"));
+		   ADDLIST1("ANALYZE"));
 	else if (Matches2("VACUUM", "ANALYZE"))
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
-		   ADDLIST1("", "VERBOSE"));
+		   ADDLIST1("VERBOSE"));
 	else if (HeadMatches1("VACUUM"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "");
 
 /* WITH [RECURSIVE] */
 
@@ -3335,7 +3344,7 @@ psql_completion(const char *text, int start, int end)
 /* ANALYZE */
 	/* Complete with list of tables */
 	else if (Matches1("ANALYZE"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, "");
 
 /* WHERE */
 	/* Simple case of the word before the where being the table name */
@@ -3345,11 +3354,11 @@ psql_completion(const char *text, int start, int end)
 /* ... FROM ... */
 /* TODO: also include SRF ? */
 	else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, "");
 
 /* ... JOIN ... */
 	else if (TailMatches1("JOIN"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, "");
 
 /* Backslash commands */
 /* TODO:  \dc \dd \dl */
@@ -3358,84 +3367,84 @@ psql_completion(const char *text, int start, int end)
 	else if (TailMatchesCS1("\\connect|\\c"))
 	{
 		if (!recognized_connection_string(text))
-			COMPLETE_WITH_QUERY(Query_for_list_of_databases);
+			COMPLETE_WITH_QUERY(Query_for_list_of_databases, "");
 	}
 	else if (TailMatchesCS2("\\connect|\\c", MatchAny))
 	{
 		if (!recognized_connection_string(prev_wd))
-			COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+			COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 	}
 	else if (TailMatchesCS1("\\da*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, "");
 	else if (TailMatchesCS1("\\dA*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
+		COMPLETE_WITH_QUERY(Query_for_list_of_access_methods, "");
 	else if (TailMatchesCS1("\\db*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
+		COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces, "");
 	else if (TailMatchesCS1("\\dD*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, "");
 	else if (TailMatchesCS1("\\des*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_servers);
+		COMPLETE_WITH_QUERY(Query_for_list_of_servers, "");
 	else if (TailMatchesCS1("\\deu*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
+		COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings, "");
 	else if (TailMatchesCS1("\\dew*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
+		COMPLETE_WITH_QUERY(Query_for_list_of_fdws, "");
 	else if (TailMatchesCS1("\\df*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, "");
 
 	else if (TailMatchesCS1("\\dFd*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
+		COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries, "");
 	else if (TailMatchesCS1("\\dFp*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
+		COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers, "");
 	else if (TailMatchesCS1("\\dFt*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
+		COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates, "");
 	/* must be at end of \dF alternatives: */
 	else if (TailMatchesCS1("\\dF*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
+		COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations, "");
 
 	else if (TailMatchesCS1("\\di*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, "");
 	else if (TailMatchesCS1("\\dL*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_languages);
+		COMPLETE_WITH_QUERY(Query_for_list_of_languages, "");
 	else if (TailMatchesCS1("\\dn*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
+		COMPLETE_WITH_QUERY(Query_for_list_of_schemas, "");
 	else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, "");
 	else if (TailMatchesCS1("\\ds*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, "");
 	else if (TailMatchesCS1("\\dt*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
 	else if (TailMatchesCS1("\\dT*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, "");
 	else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 	else if (TailMatchesCS1("\\dv*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, "");
 	else if (TailMatchesCS1("\\dx*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
+		COMPLETE_WITH_QUERY(Query_for_list_of_extensions, "");
 	else if (TailMatchesCS1("\\dm*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, "");
 	else if (TailMatchesCS1("\\dE*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, "");
 	else if (TailMatchesCS1("\\dy*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
+		COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers, "");
 
 	/* must be at end of \d alternatives: */
 	else if (TailMatchesCS1("\\d*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, "");
 
 	else if (TailMatchesCS1("\\ef"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, "");
 	else if (TailMatchesCS1("\\ev"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, "");
 
 	else if (TailMatchesCS1("\\encoding"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
+		COMPLETE_WITH_QUERY(Query_for_list_of_encodings, "");
 	else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
 		COMPLETE_WITH_LIST(sql_commands);
 	else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_databases);
+		COMPLETE_WITH_QUERY(Query_for_list_of_databases, "");
 	else if (TailMatchesCS1("\\password"))
-		COMPLETE_WITH_QUERY(Query_for_list_of_roles);
+		COMPLETE_WITH_QUERY(Query_for_list_of_roles, "");
 	else if (TailMatchesCS1("\\pset"))
 	{
 		static const char *const my_list[] =
@@ -3495,14 +3504,14 @@ psql_completion(const char *text, int start, int end)
 			COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
 	}
 	else if (TailMatchesCS1("\\sf*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, "");
 	else if (TailMatchesCS1("\\sv*"))
-		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
+		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, "");
 	else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
 							"\\ir|\\include_relative|\\o|\\out|"
 							"\\s|\\w|\\write|\\lo_import"))
 	{
-		completion_charp = "\\";
+		SET_COMP_CHARP("\\");
 		matches = completion_matches(text, complete_from_files);
 	}
 
@@ -3518,9 +3527,9 @@ psql_completion(const char *text, int start, int end)
 		if (ent)
 		{
 			if (ent->query)
-				COMPLETE_WITH_QUERY(ent->query);
+				COMPLETE_WITH_QUERY(ent->query, "");
 			else if (ent->squery)
-				COMPLETE_WITH_SCHEMA_QUERY(*ent->squery, NULL);
+				COMPLETE_WITH_SCHEMA_QUERY(*ent->squery, "");
 		}
 	}
 
@@ -3782,13 +3791,13 @@ _complete_from_query(int is_schema_query, const char *text, int state)
 							  char_length, e_text);
 
 			/* If an addon query was provided, use it */
-			if (completion_charp)
-				appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
+			if (COMPLETION_CHARP[0])
+				appendPQExpBuffer(&query_buffer, "\n%s", COMPLETION_CHARP);
 		}
 		else
 		{
 			/* completion_charp is an sprintf-style format string */
-			appendPQExpBuffer(&query_buffer, completion_charp,
+			appendPQExpBuffer(&query_buffer, COMPLETION_CHARP,
 							  char_length, e_text,
 							  e_info_charp, e_info_charp,
 							  e_info_charp2, e_info_charp2);
@@ -3903,18 +3912,17 @@ complete_from_list(const char *text, int state)
 static char *
 complete_from_const(const char *text, int state)
 {
-	Assert(completion_charp != NULL);
 	if (state == 0)
 	{
 		if (completion_case_sensitive)
-			return pg_strdup(completion_charp);
+			return pg_strdup(COMPLETION_CHARP);
 		else
 
 			/*
 			 * If case insensitive matching was requested initially, adjust
 			 * the case according to setting.
 			 */
-			return pg_strdup_keyword_case(completion_charp, text);
+			return pg_strdup_keyword_case(COMPLETION_CHARP, text);
 	}
 	else
 		return NULL;
@@ -4015,7 +4023,7 @@ complete_from_files(const char *text, int state)
 	if (state == 0)
 	{
 		/* Initialization: stash the unquoted input. */
-		unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
+		unquoted_text = strtokx(text, "", NULL, "'", COMPLETION_CHARP[0],
 								false, true, pset.encoding);
 		/* expect a NULL return for the empty string only */
 		if (!unquoted_text)
@@ -4036,7 +4044,7 @@ complete_from_files(const char *text, int state)
 		 * bother providing a macro to simplify this.
 		 */
 		ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
-							  '\'', *completion_charp, pset.encoding);
+							  '\'', COMPLETION_CHARP[0], pset.encoding);
 		if (ret)
 			free(unquoted_match);
 		else
@@ -4094,7 +4102,7 @@ pg_strdup_keyword_case(const char *s, const char *ref)
 
 /* Construct codelet to append given keywords  */
 static char *
-additional_kw_query(char *prefix, const char *ref, int n, ...)
+additional_kw_query(const char *ref, int n, ...)
 {
 	va_list ap;
 	static PQExpBuffer qbuf = NULL;
@@ -4105,8 +4113,6 @@ additional_kw_query(char *prefix, const char *ref, int n, ...)
 	else
 		resetPQExpBuffer(qbuf);
 
-	appendPQExpBufferStr(qbuf, prefix);
-
 	/* Construct an additional queriy to append keywords */
 	appendPQExpBufferStr(qbuf, " UNION SELECT * FROM (VALUES ");
 
-- 
2.9.2


----Next_Part(Tue_Sep_06_22_00_26_2016_037)--
Content-Type: Text/X-Patch; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="0004-Refactoring-tab-complete-to-make-psql_completion-cod.patch"



view thread (21+ 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 3/4] Make COMPLETE_WITH_ATTR to accept additional keyword query.
  In-Reply-To: <no-message-id-632694@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