From 116c23b5326b937a4c39ae47c43b61aa74a7da9c Mon Sep 17 00:00:00 2001 From: Kyotaro Horiguchi Date: Tue, 29 Mar 2016 19:01:13 +0900 Subject: [PATCH 2/4] Make added keywords for 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. Only COMPLETE_WITH_QUERY/COMPLETE_WITH_SCHEMA_QUERY are fixed. --- src/bin/psql/tab-complete.c | 235 +++++++++++++++++++++++++------------------- 1 file changed, 134 insertions(+), 101 deletions(-) diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index d957a35..c530fcb 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 */ @@ -963,6 +975,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); @@ -1448,8 +1461,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")); + /* ALTER TABLE after removing optional words IF EXISTS*/ else if (HeadMatches2("ALTER", "TABLE") && MidMatchAndRemove2(2, "IF", "EXISTS") && @@ -1549,7 +1562,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")); /* ALTER|DROP FOREIGN TABLE after removing optinal words IF EXISTS */ else if (HeadMatches3("ALTER|DROP", "FOREIGN", "TABLE") && @@ -1575,8 +1588,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")); /* ALTER INDEX after removing optional words IF EXISTS */ else if (HeadMatches2("ALTER", "INDEX") && MidMatchAndRemove2(2, "IF", "EXISTS") && @@ -1611,8 +1623,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")); /* ALTER MATERIALIZED VIEW with name after removing optional words */ else if (HeadMatches3("ALTER", "MATERIALIZED", "VIEW") && @@ -1680,8 +1691,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") && @@ -1703,7 +1714,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")); /* ALTER SEQUENCE with name after removing optional words IF EXISTS */ else if (HeadMatches2("ALTER", "SEQUENCE") && MidMatchAndRemove2(2, "IF", "EXISTS") && @@ -1733,7 +1744,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")); /* ALTER VIEW with subcommands after removing optional worlds */ else if (HeadMatches2("ALTER", "VIEW") && MidMatchAndRemove2(2, "IF", "EXISTS") && @@ -1747,8 +1758,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")); /* ALTER POLICY with ON after removing optional words IF EXISTS */ else if (HeadMatches2("ALTER", "POLICY") && MidMatchAndRemove2(2, "IF", "EXISTS") && @@ -1923,8 +1934,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") && @@ -2122,7 +2133,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 , then add "USING" */ @@ -2187,7 +2199,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); @@ -2242,8 +2254,8 @@ psql_completion(const char *text, int start, int end) /* CREATE EXTENSION */ /* Complete with available extensions rather than installed ones. */ else if (Matches2("CREATE", "EXTENSION")) - COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions - " UNION SELECT 'IF NOT EXISTS'"); + COMPLETE_WITH_QUERY(ADDLIST1(Query_for_list_of_available_extensions, + "IF NOT EXISTS")); /* Try the same after removing optional words IF NOT EXISTS */ else if (HeadMatches2("CREATE", "EXTENSION") && MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") && @@ -2266,7 +2278,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") && @@ -2288,15 +2300,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") && @@ -2388,7 +2397,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, - " UNION SELECT 'IF NOT EXISTS'"); + ADDLIST1("", "IF NOT EXISTS")); else if(HeadMatches2("CREATE", "SEQUENCE") && MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") && Matches3("CREATE", "SEQUENCE", MatchAny)) @@ -2403,8 +2412,8 @@ psql_completion(const char *text, int start, int end) /* CREATE SCHEMA */ 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") && @@ -2424,7 +2433,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, - " UNION SELECT 'IF NOT EXISTS'"); + ADDLIST1("", "IF NOT EXISTS")); /* Remove optional words here */ else if (HeadMatches2("CREATE", "TABLE") && @@ -2515,7 +2524,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")); /* CREATE VIEW with AS after removing optional words */ else if (HeadMatches2("CREATE", "VIEW") && MidMatchAndRemove3(2, "IF", "NOT", "EXISTS") && @@ -2530,7 +2539,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") && @@ -2598,10 +2607,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") && @@ -2612,8 +2621,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") && @@ -2622,11 +2631,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") && @@ -2639,14 +2647,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") && @@ -2664,8 +2672,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") && @@ -2689,8 +2697,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") && @@ -2699,8 +2707,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") && @@ -2718,8 +2726,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 , after removing optional words IF EXISTS */ else if (HeadMatches2("DROP", "RULE") && MidMatchAndRemove2(2, "IF", "EXISTS") && @@ -2743,7 +2751,7 @@ psql_completion(const char *text, int start, int end) { const pgsql_thing_t *ent = find_thing_entry(prev_wd); - char *addition = " UNION SELECT 'IF EXISTS'"; + char *addition = ADDLIST1("", "IF EXISTS"); if (ent) { @@ -2764,7 +2772,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 */ @@ -2835,20 +2843,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 with "ON", GRANT/REVOKE with @@ -2877,21 +2876,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", @@ -3017,7 +3017,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, ""); @@ -3083,7 +3083,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)) @@ -3175,7 +3175,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 with DEFERRED|IMMEDIATE */ else if (Matches3("SET", "CONSTRAINTS", MatchAny)) COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE"); @@ -3187,7 +3188,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"); @@ -3213,10 +3215,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 */ @@ -3285,10 +3288,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)) @@ -3302,26 +3304,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); @@ -4094,6 +4092,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. -- 2.9.2