From: Kyotaro Horiguchi Date: Thu, 15 Sep 2016 20:49:45 +0900 Subject: [PATCH 5/6] Add suggestion for IF (NOT) EXISTS for some syntaxes Add suggestion for IF EXISTS or IF NOT EXISTS for some arbitrary syntaxes, ALTER TABLE/ALTER FOREIGN TABLE/ALTER INDEX/ ALTER MATERIALIZED VIEW/ALTER DOMAIN DROP CONSTRAINT/ALTER SEQUENCE/ ALTER VIEW/ALTER POLICY/ALTER TABLE DROP COLUMN/ ALTER TABLE DROP CONSTRAINT/CREATE INDEX/CREATE SEQUENCE/ CREATE TABLE/CREATE VIEW/DROP INDEX/DROP (MATERIALIZED) VIEW/ DROP USER MAPPING --- src/bin/psql/tab-complete.c | 178 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 168 insertions(+), 10 deletions(-) diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index ec5a700..cbac5d3 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -1094,7 +1094,9 @@ psql_completion_internal(const char *text, char **previous_words, /* ALTER TABLE */ if (Matches2("ALTER", "TABLE")) COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables, - ADDLIST1("ALL IN TABLESPACE")); + ADDLIST2("ALL IN TABLESPACE", "IF EXISTS")); + if (HeadMatches4("ALTER", "TABLE", "IF", "EXISTS")) + COLLAPSE(3, 2); /* ALTER something */ if (Matches1("ALTER")) @@ -1197,6 +1199,14 @@ psql_completion_internal(const char *text, char **previous_words, if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny)) COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO"); + /* ALTER FOREIGN TABLE */ + if (Matches3("ALTER", "FOREIGN", "TABLE")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_foreign_tables, + ADDLIST1("IF EXISTS")); + /* Remove optional words for further completion */ + if (HeadMatches5("ALTER", "FOREIGN", "TABLE", "IF", "EXISTS")) + COLLAPSE(4, 2); + /* ALTER FOREIGN TABLE */ if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny)) { @@ -1211,7 +1221,11 @@ psql_completion_internal(const char *text, char **previous_words, /* ALTER INDEX */ if (Matches2("ALTER", "INDEX")) COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes, - ADDLIST1("ALL IN TABLESPACE")); + ADDLIST2("ALL IN TABLESPACE", "IF EXISTS")); + /* Remove optional words for further completion */ + if (HeadMatches4("ALTER", "INDEX", "IF", "EXISTS")) + COLLAPSE(3, 2); + /* ALTER INDEX */ if (Matches3("ALTER", "INDEX", MatchAny)) COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET"); @@ -1240,7 +1254,10 @@ psql_completion_internal(const char *text, char **previous_words, /* ALTER MATERIALIZED VIEW */ if (Matches3("ALTER", "MATERIALIZED", "VIEW")) COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews, - ADDLIST1("ALL IN TABLESPACE")); + ADDLIST2("ALL IN TABLESPACE", "IF EXISTS")); + /* Remove optional words for further completion */ + if (HeadMatches5("ALTER", "MATERIALIZED", "VIEW", "IF", "EXISTS")) + COLLAPSE(4, 2); /* ALTER USER,ROLE */ if (Matches3("ALTER", "USER|ROLE", MatchAny) && @@ -1296,6 +1313,19 @@ psql_completion_internal(const char *text, char **previous_words, if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT")) { completion_info_charp = prev3_wd; + if (word_matches("DROP", prev2_wd)) + COMPLETE_WITH_QUERY_KW(Query_for_constraint_of_type, + ADDLIST1("IF EXISTS")); + else + COMPLETE_WITH_QUERY(Query_for_constraint_of_type); + } + /* Remove optional words for further completion */ + if (HeadMatches7("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT", "IF", "EXISTS")) + COLLAPSE(6, 2); + /* Complete constraint name again without IF EXISTS */ + if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT")) + { + completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_constraint_of_type); } /* ALTER DOMAIN RENAME */ @@ -1308,6 +1338,16 @@ psql_completion_internal(const char *text, char **previous_words, /* ALTER DOMAIN SET */ if (Matches4("ALTER", "DOMAIN", MatchAny, "SET")) COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA"); + /* ALTER SEQUENCE */ + if (Matches2("ALTER", "SEQUENCE")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_sequences, + ADDLIST1("IF EXISTS")); + /* Remove optional words for further completion */ + if (HeadMatches4("ALTER", "SEQUENCE", "IF", "EXISTS")) + COLLAPSE(3, 2); + /* Complete again without IF EXISTS */ + if (Matches2("ALTER", "SEQUENCE")) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences); /* ALTER SEQUENCE */ if (Matches3("ALTER", "SEQUENCE", MatchAny)) { @@ -1333,6 +1373,16 @@ psql_completion_internal(const char *text, char **previous_words, if (Matches3("ALTER", "SYSTEM", "SET|RESET")) COMPLETE_WITH_QUERY_KW(Query_for_list_of_alter_system_set_vars, ADDLIST1("ALL")); + /* ALTER VIEW */ + if (Matches2("ALTER", "VIEW")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views, + ADDLIST1("IF EXISTS")); + /* Remove optional words for further completion */ + if (HeadMatches4("ALTER", "VIEW", "IF", "EXISTS")) + COLLAPSE(3, 2); + /* Complete again without IF EXISTS */ + if (Matches2("ALTER", "VIEW")) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views); /* ALTER VIEW */ if (Matches3("ALTER", "VIEW", MatchAny)) COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO", @@ -1344,6 +1394,12 @@ psql_completion_internal(const char *text, char **previous_words, /* ALTER POLICY */ if (Matches2("ALTER", "POLICY")) + COMPLETE_WITH_QUERY_KW(Query_for_list_of_policies, ADDLIST1("IF EXISTS")); + /* Remove optional words for further completion */ + if (Matches4("ALTER", "POLICY", "IF", "EXISTS")) + COLLAPSE(3, 2); + /* Complete again without IF EXISTS */ + if (Matches2("ALTER", "POLICY")) COMPLETE_WITH_QUERY(Query_for_list_of_policies); /* ALTER POLICY ON */ if (Matches3("ALTER", "POLICY", MatchAny)) @@ -1483,8 +1539,13 @@ psql_completion_internal(const char *text, char **previous_words, COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT"); /* If we have ALTER TABLE DROP COLUMN, provide list of columns */ if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN")) + COMPLETE_WITH_ATTR_KW(prev3_wd, ADDLIST1("IF EXISTS")); + /* Remove optional words for further completion */ + if (HeadMatches7("ALTER", "TABLE", MatchAny, "DROP", "COLUMN", "IF", "EXISTS")) + COLLAPSE(6, 2); + /* Complete again without IF EXISTS */ + if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN")) COMPLETE_WITH_ATTR(prev3_wd); - /* * If we have ALTER TABLE ALTER|DROP|RENAME|VALIDATE CONSTRAINT, * provide list of constraints @@ -1492,6 +1553,19 @@ psql_completion_internal(const char *text, char **previous_words, if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT")) { completion_info_charp = prev3_wd; + if (word_matches("DROP", prev2_wd)) + COMPLETE_WITH_QUERY_KW(Query_for_constraint_of_table, + ADDLIST1("IF EXISTS")); + else + COMPLETE_WITH_QUERY(Query_for_constraint_of_table); + } + /* Remove IF EXISTS for further completion */ + if (HeadMatches7("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT", "IF", "EXISTS")) + COLLAPSE(6, 2); + /* Complete again without IF EXISTS */ + if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT")) + { + completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_constraint_of_table); } /* Remove COLUMN just after ALTER */ @@ -1633,7 +1707,18 @@ psql_completion_internal(const char *text, char **previous_words, * of attributes */ if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE")) - COMPLETE_WITH_ATTR(prev3_wd); + { + if (word_matches("DROP", prev2_wd)) + COMPLETE_WITH_ATTR_KW(prev3_wd, ADDLIST1("IF EXISTS")); + else + COMPLETE_WITH_ATTR(prev3_wd); + } + /* Remove IF EXISTS for further completion */ + if (HeadMatches7("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE", "IF", "EXISTS")) + COLLAPSE(6, 2); + /* Complete again without IF EXISTS */ + if (Matches5("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE")) + COMPLETE_WITH_ATTR(prev3_wd); /* ALTER TYPE ALTER ATTRIBUTE */ if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny)) COMPLETE_WITH_CONST("TYPE"); @@ -1787,6 +1872,13 @@ psql_completion_internal(const char *text, char **previous_words, /* CREATE EXTENSION */ /* Complete with available extensions rather than installed ones. */ if (Matches2("CREATE", "EXTENSION")) + COMPLETE_WITH_QUERY_KW(Query_for_list_of_available_extensions, + ADDLIST1("IF NOT EXISTS")); + /* Remove IF NOT EXISTS for further completion*/ + if (HeadMatches5("CREATE", "EXTENSION", "IF", "NOT", "EXISTS")) + COLLAPSE(3, 3); + /* Complete again without IF NOT EXISTS */ + if (Matches2("CREATE", "EXTENSION")) COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions); /* CREATE EXTENSION */ if (Matches3("CREATE", "EXTENSION", MatchAny)) @@ -1817,14 +1909,20 @@ psql_completion_internal(const char *text, char **previous_words, /* Complete with index names as category suggestion and possible keywords */ if (Matches2("CREATE", "INDEX")) COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes, - ADDLIST2("ON", "CONCURRENTLY")); + ADDLIST3("ON", "CONCURRENTLY", "IF NOT EXISTS")); /* Remove CONCURRENTLY for further completion */ if (HeadMatches3("CREATE", "INDEX", "CONCURRENTLY")) COLLAPSE(3, 1); /* Complete with existing index names as word category suggestion */ if (Matches2("CREATE", "INDEX")) COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes, - ADDLIST1("ON")); + ADDLIST2("ON", "IF NOT EXISTS")); + /* Remove IF NOT EXISTS for further completion */ + if (HeadMatches5("CREATE", "INDEX", "IF", "NOT", "EXISTS")) + COLLAPSE(3, 3); + /* Complete again without IF NOT EXISTS */ + if (Matches2("CREATE", "INDEX")) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes); /* Suggest ON just after index name */ if (Matches3("CREATE", "INDEX", MatchAnyExcept("ON"))) COMPLETE_WITH_CONST("ON"); @@ -1917,6 +2015,13 @@ psql_completion_internal(const char *text, char **previous_words, /* CREATE SEQUENCE */ if (Matches2("CREATE", "SEQUENCE")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_sequences, + ADDLIST1("IF NOT EXISTS")); + /* Remove IF NOT EXISTS for further completion */ + if (HeadMatches5("CREATE", "SEQUENCE", "IF", "NOT", "EXISTS")) + COLLAPSE(3, 3); + /* Complete again without IF NOT EXISTS */ + if (Matches2("CREATE", "SEQUENCE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences); if (Matches3("CREATE", "SEQUENCE", MatchAny)) COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", @@ -1942,6 +2047,13 @@ psql_completion_internal(const char *text, char **previous_words, COLLAPSE(2, 1); /* Complete CREATE TABLE with existing table names */ if (Matches2("CREATE", "TABLE")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables, + ADDLIST1("IF NOT EXISTS")); + /* Remove IF NOT EXIST for further completion */ + if (HeadMatches5("CREATE", "TABLE", "IF", "NOT", "EXISTS")) + COLLAPSE(3, 3); + /* Complete again without IF NOT EXISTS */ + if (Matches2("CREATE", "TABLE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables); /* CREATE TABLESPACE */ @@ -2134,6 +2246,16 @@ psql_completion_internal(const char *text, char **previous_words, COMPLETE_WITH_LIST2("GROUP", "ROLE"); /* CREATE VIEW */ + /* Complete CREATE VIEW with name */ + if (Matches2("CREATE", "VIEW")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views, + ADDLIST1("IF NOT EXISTS")); + /* Remove IF NOT EXISTS for further completion */ + if (HeadMatches5("CREATE", "VIEW", "IF", "NOT", "EXISTS")) + COLLAPSE(3, 3); + /* Complete again without IF NOT EXISTS */ + if (Matches2("CREATE", "VIEW")) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views); /* Complete CREATE VIEW with AS */ if (Matches3("CREATE", "VIEW", MatchAny)) COMPLETE_WITH_CONST("AS"); @@ -2213,18 +2335,43 @@ psql_completion_internal(const char *text, char **previous_words, /* DROP INDEX */ if (Matches2("DROP", "INDEX")) COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes, - ADDLIST1("CONCURRENTLY")); + ADDLIST2("CONCURRENTLY", "IF EXISTS")); + if (Matches3("DROP", "INDEX", "CONCURRENTLY")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes, + ADDLIST1("IF EXISTS")); if (HeadMatches3("DROP", "INDEX", "CONCURRENTLY")) COLLAPSE(3, 1); + /* Remove IF EXISTS for further completion */ + if (HeadMatches4("DROP", "INDEX", "IF", "EXISTS")) + COLLAPSE(3, 2); + /* Complete again without IF EXISTS */ + if (Matches2("DROP", "INDEX")) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes); if (Matches3("DROP", "INDEX", MatchAny)) COMPLETE_WITH_LIST2("CASCADE", "RESTRICT"); + /* DROP VIEW */ + if (Matches2("DROP", "VIEW")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views, + ADDLIST1("IF EXISTS")); + /* Remove IF EXISTS for further completion */ + if (HeadMatches4("DROP", "VIEW", "IF", "EXISTS")) + COLLAPSE(3, 2); + /* Complet again without IF EXISTS */ + if (Matches2("DROP", "VIEW")) + COMPLETE_THING(-1); + /* DROP MATERIALIZED VIEW */ if (Matches2("DROP", "MATERIALIZED")) COMPLETE_WITH_CONST("VIEW"); - /* DROP VIEW is suggested as a general thing */ - + if (Matches3("DROP", "MATERIALIZED", "VIEW")) + COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews, + ADDLIST1("IF EXISTS")); + /* Remove IF EXISTS for further completion */ + if (HeadMatches5("DROP", "MATERIALIZED", "VIEW", "IF", "EXISTS")) + COLLAPSE(4, 2); + /* Complet again without IF EXISTS */ if (Matches3("DROP", "MATERIALIZED", "VIEW")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews); @@ -2791,6 +2938,17 @@ psql_completion_internal(const char *text, char **previous_words, /* USER MAPPING */ if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING")) + { + if (word_matches("DROP", prev3_wd)) + COMPLETE_WITH_LIST2("FOR", "IF EXISTS FOR"); + else + COMPLETE_WITH_CONST("FOR"); + } + /* Remove IF EXISTS for further completion */ + if (HeadMatches5("DROP", "USER", "MAPPING", "IF", "EXISTS")) + COLLAPSE(4, 2); + /* Complete again without IF EXISTS */ + if (Matches3("DROP", "USER", "MAPPING")) COMPLETE_WITH_CONST("FOR"); if (Matches4("CREATE", "USER", "MAPPING", "FOR")) COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles, -- 2.9.2 ----Next_Part(Tue_Nov_15_20_26_42_2016_708)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="0006-Add-README-for-tab-completion.patch"