diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 816deda..6108ce3 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -228,6 +228,62 @@ do { \ matches = completion_matches(text, complete_from_query); \ } while (0) +#define COMPLETE_WITH_LIST2(s1, s2) \ +do { \ + static const char *const list[] = { s1, s2, NULL }; \ + completion_charpp = list; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + +#define COMPLETE_WITH_LIST3(s1, s2, s3) \ +do { \ + static const char *const list[] = { s1, s2, s3, NULL }; \ + completion_charpp = list; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + +#define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \ +do { \ + static const char *const list[] = { s1, s2, s3, s4, NULL }; \ + completion_charpp = list; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + +#define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \ +do { \ + static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \ + completion_charpp = list; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + +#define COMPLETE_WITH_LIST6(s1, s2, s3, s4, s5, s6) \ +do { \ + static const char *const list[] = { s1, s2, s3, s4, s5, s6, NULL }; \ + completion_charpp = list; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + +#define COMPLETE_WITH_LIST7(s1, s2, s3, s4, s5, s6, s7) \ +do { \ + static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, NULL }; \ + completion_charpp = list; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + +#define COMPLETE_WITH_LIST8(s1, s2, s3, s4, s5, s6, s7, s8) \ +do { \ + static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, NULL }; \ + completion_charpp = list; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + /* * Assembly instructions for schema queries */ @@ -872,6 +928,54 @@ initialize_readline(void) */ } +/* + * Check if 'word' matches any of the '|'-separated strings in 'pattern', using + * case-insensitive comparison, or the pattern begins with '<' indicating a + * wildcard that matches any word. + */ +static bool +word_matches(const char *pattern, const char *word) +{ + const char *c = word; + + if (pattern[0] == '<') + return true; + + while (*pattern != '\0') + { + if (*c == '\0' && *pattern == '|') + return true; + else if (*c == '\0' || tolower(*pattern) != tolower(*c)) + { + /* Skip to next word in pattern and rewind word. */ + while (*pattern != '\0' && *pattern != '|') + ++pattern; + if (*pattern == '\0') + return false; + else + ++pattern; + c = word; + } + else + { + ++pattern; + ++c; + } + } + + return *c == '\0'; +} + +/* + * Check if the final character of 's' is 'c'. + */ +static bool +ends_with(const char *s, char c) +{ + size_t length = strlen(s); + + return length > 0 && s[length - 1] == c; +} /* * The completion function. @@ -898,6 +1002,58 @@ psql_completion(const char *text, int start, int end) #define prev5_wd (previous_words[4]) #define prev6_wd (previous_words[5]) +#define MATCHES1(p1) \ +(word_matches(p1, prev_wd)) \ + +#define MATCHES2(p2, p1) \ +(word_matches(p1, prev_wd) && \ + word_matches(p2, prev2_wd)) + +#define MATCHES3(p3, p2, p1) \ +(word_matches(p1, prev_wd) && \ + word_matches(p2, prev2_wd) && \ + word_matches(p3, prev3_wd)) + +#define MATCHES4(p4, p3, p2, p1) \ +(word_matches(p1, prev_wd) && \ + word_matches(p2, prev2_wd) && \ + word_matches(p3, prev3_wd) && \ + word_matches(p4, prev4_wd)) + +#define MATCHES5(p5, p4, p3, p2, p1) \ +(word_matches(p1, prev_wd) && \ + word_matches(p2, prev2_wd) && \ + word_matches(p3, prev3_wd) && \ + word_matches(p4, prev4_wd) && \ + word_matches(p5, prev5_wd)) + +#define MATCHES6(p6, p5, p4, p3, p2, p1) \ +(word_matches(p1, prev_wd) && \ + word_matches(p2, prev2_wd) && \ + word_matches(p3, prev3_wd) && \ + word_matches(p4, prev4_wd) && \ + word_matches(p5, prev5_wd) && \ + word_matches(p6, prev6_wd)) + +#define MATCHES7(p7, p6, p5, p4, p3, p2, p1) \ +(word_matches(p1, prev_wd) && \ + word_matches(p2, prev2_wd) && \ + word_matches(p3, prev3_wd) && \ + word_matches(p4, prev4_wd) && \ + word_matches(p5, prev5_wd) && \ + word_matches(p6, prev6_wd) && \ + word_matches(p7, prev7_wd)) + +#define MATCHES8(p8, p7, p6, p5, p4, p3, p2, p1) \ +(word_matches(p1, prev_wd) && \ + word_matches(p2, prev2_wd) && \ + word_matches(p3, prev3_wd) && \ + word_matches(p4, prev4_wd) && \ + word_matches(p5, prev5_wd) && \ + word_matches(p6, prev6_wd) && \ + word_matches(p7, prev7_wd) && \ + word_matches(p8, prev8_wd)) + static const char *const sql_commands[] = { "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", @@ -931,6 +1087,22 @@ psql_completion(const char *text, int start, int end) rl_completion_append_character = ' '; #endif + /* TODO:TM -- begin temporary, not part of the patch! */ + Assert(word_matches("", "")); + Assert(word_matches("", "walrus")); + Assert(word_matches("", "")); + Assert(word_matches("a", "A")); + Assert(word_matches("ab", "Ab")); + Assert(!word_matches("ab", "b")); + Assert(word_matches("a|b", "b")); + Assert(word_matches("a|b|c", "b")); + Assert(!word_matches("a|b|c", "d")); + Assert(!word_matches("a|b|c", "bb")); + Assert(word_matches("|foo", "")); + Assert(word_matches("foo|", "")); + Assert(!word_matches("foo", "")); + /* TODO:TM -- end temorary */ + /* Clear a few things. */ completion_charp = NULL; completion_charpp = NULL; @@ -960,36 +1132,31 @@ psql_completion(const char *text, int start, int end) } /* If no previous word, suggest one of the basic sql commands */ - else if (prev_wd[0] == '\0') + else if (MATCHES1("")) COMPLETE_WITH_LIST(sql_commands); /* CREATE */ /* complete with something you can create */ - else if (pg_strcasecmp(prev_wd, "CREATE") == 0) + else if (MATCHES1("CREATE")) matches = completion_matches(text, create_command_generator); /* DROP, but not DROP embedded in other commands */ /* complete with something you can drop */ - else if (pg_strcasecmp(prev_wd, "DROP") == 0 && - prev2_wd[0] == '\0') + else if (MATCHES2("", "DROP")) matches = completion_matches(text, drop_command_generator); /* ALTER */ /* ALTER TABLE */ - else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && - pg_strcasecmp(prev_wd, "TABLE") == 0) - { + else if (MATCHES2("ALTER", "TABLE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "UNION SELECT 'ALL IN TABLESPACE'"); - } /* * complete with what you can alter (TABLE, GROUP, USER, ...) unless we're * in ALTER TABLE sth ALTER */ - else if (pg_strcasecmp(prev_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TABLE") != 0) + else if (MATCHES3("TABLE", "", "ALTER")) { static const char *const list_ALTER[] = {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN", @@ -1002,9 +1169,7 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_ALTER); } /* ALTER TABLE,INDEX,MATERIALIZED VIEW xxx ALL IN TABLESPACE xxx */ - else if (pg_strcasecmp(prev4_wd, "ALL") == 0 && - pg_strcasecmp(prev3_wd, "IN") == 0 && - pg_strcasecmp(prev2_wd, "TABLESPACE") == 0) + else if (MATCHES4("ALL", "IN", "TABLESPACE", "")) { static const char *const list_ALTERALLINTSPC[] = {"SET TABLESPACE", "OWNED BY", NULL}; @@ -1017,20 +1182,14 @@ psql_completion(const char *text, int start, int end) pg_strcasecmp(prev4_wd, "TABLESPACE") == 0 && pg_strcasecmp(prev2_wd, "OWNED") == 0 && pg_strcasecmp(prev4_wd, "BY") == 0) - { COMPLETE_WITH_QUERY(Query_for_list_of_roles); - } /* ALTER AGGREGATE,FUNCTION */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - (pg_strcasecmp(prev2_wd, "AGGREGATE") == 0 || - pg_strcasecmp(prev2_wd, "FUNCTION") == 0)) + else if (MATCHES3("ALTER", "AGGREGATE|FUNCTION", "")) COMPLETE_WITH_CONST("("); /* ALTER AGGREGATE,FUNCTION (...) */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - (pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 || - pg_strcasecmp(prev3_wd, "FUNCTION") == 0)) + else if (MATCHES4("ALTER", "AGGREGATE|FUNCTION", "", "<...>")) { - if (prev_wd[strlen(prev_wd) - 1] == ')') + if (ends_with(prev_wd, ')')) { static const char *const list_ALTERAGG[] = {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; @@ -1042,38 +1201,19 @@ psql_completion(const char *text, int start, int end) } /* ALTER SCHEMA */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "SCHEMA") == 0) - { - static const char *const list_ALTERGEN[] = - {"OWNER TO", "RENAME TO", NULL}; - - COMPLETE_WITH_LIST(list_ALTERGEN); - } + else if (MATCHES3("ALTER", "SCHEMA", "")) + COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO"); /* ALTER COLLATION */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "COLLATION") == 0) - { - static const char *const list_ALTERGEN[] = - {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERGEN); - } + else if (MATCHES3("ALTER", "COLLATION", "")) + COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA"); /* ALTER CONVERSION */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "CONVERSION") == 0) - { - static const char *const list_ALTERGEN[] = - {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERGEN); - } + else if (MATCHES3("ALTER", "CONVERSION", "")) + COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA"); /* ALTER DATABASE */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "DATABASE") == 0) + else if (MATCHES3("ALTER", "DATABASE", "")) { static const char *const list_ALTERDATABASE[] = {"RESET", "SET", "OWNER TO", "RENAME TO", "IS_TEMPLATE", @@ -1083,72 +1223,31 @@ psql_completion(const char *text, int start, int end) } /* ALTER EVENT TRIGGER */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "EVENT") == 0 && - pg_strcasecmp(prev_wd, "TRIGGER") == 0) - { + else if (MATCHES3("ALTER", "EVENT", "TRIGGER")) COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers); - } /* ALTER EVENT TRIGGER */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "EVENT") == 0 && - pg_strcasecmp(prev2_wd, "TRIGGER") == 0) - { - static const char *const list_ALTER_EVENT_TRIGGER[] = - {"DISABLE", "ENABLE", "OWNER TO", "RENAME TO", NULL}; - - COMPLETE_WITH_LIST(list_ALTER_EVENT_TRIGGER); - } + else if (MATCHES4("ALTER", "EVENT", "TRIGGER", "")) + COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO"); /* ALTER EVENT TRIGGER ENABLE */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "EVENT") == 0 && - pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && - pg_strcasecmp(prev_wd, "ENABLE") == 0) - { - static const char *const list_ALTER_EVENT_TRIGGER_ENABLE[] = - {"REPLICA", "ALWAYS", NULL}; - - COMPLETE_WITH_LIST(list_ALTER_EVENT_TRIGGER_ENABLE); - } + else if (MATCHES5("ALTER", "EVENT", "TRIGGER", "", "ENABLE")) + COMPLETE_WITH_LIST2("REPLICA", "ALWAYS"); /* ALTER EXTENSION */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "EXTENSION") == 0) - { - static const char *const list_ALTEREXTENSION[] = - {"ADD", "DROP", "UPDATE", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTEREXTENSION); - } + else if (MATCHES3("ALTER", "EXTENSION", "NAME")) + COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA"); /* ALTER FOREIGN */ - else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && - pg_strcasecmp(prev_wd, "FOREIGN") == 0) - { - static const char *const list_ALTER_FOREIGN[] = - {"DATA WRAPPER", "TABLE", NULL}; - - COMPLETE_WITH_LIST(list_ALTER_FOREIGN); - } + else if (MATCHES2("ALTER", "FOREIGN")) + COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE"); /* ALTER FOREIGN DATA WRAPPER */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "FOREIGN") == 0 && - pg_strcasecmp(prev3_wd, "DATA") == 0 && - pg_strcasecmp(prev2_wd, "WRAPPER") == 0) - { - static const char *const list_ALTER_FDW[] = - {"HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", NULL}; - - COMPLETE_WITH_LIST(list_ALTER_FDW); - } + else if (MATCHES5("ALTER", "FOREIGN", "DATA", "WRAPPER", "")) + COMPLETE_WITH_LIST4("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO"); /* ALTER FOREIGN TABLE */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "FOREIGN") == 0 && - pg_strcasecmp(prev2_wd, "TABLE") == 0) + else if (MATCHES4("ALTER", "FOREIGN", "TABLE", "")) { static const char *const list_ALTER_FOREIGN_TABLE[] = {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT", @@ -1159,84 +1258,37 @@ psql_completion(const char *text, int start, int end) } /* ALTER INDEX */ - else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && - pg_strcasecmp(prev_wd, "INDEX") == 0) - { + else if (MATCHES2("ALTER", "INDEX")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, "UNION SELECT 'ALL IN TABLESPACE'"); - } /* ALTER INDEX */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "INDEX") == 0) - { - static const char *const list_ALTERINDEX[] = - {"OWNER TO", "RENAME TO", "SET", "RESET", NULL}; - - COMPLETE_WITH_LIST(list_ALTERINDEX); - } + else if (MATCHES3("ALTER", "INDEX", "")) + COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET"); /* ALTER INDEX SET */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "INDEX") == 0 && - pg_strcasecmp(prev_wd, "SET") == 0) - { - static const char *const list_ALTERINDEXSET[] = - {"(", "TABLESPACE", NULL}; - - COMPLETE_WITH_LIST(list_ALTERINDEXSET); - } + else if (MATCHES4("ALTER", "INDEX", "", "SET")) + COMPLETE_WITH_LIST2("(", "TABLESPACE"); /* ALTER INDEX RESET */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "INDEX") == 0 && - pg_strcasecmp(prev_wd, "RESET") == 0) + else if (MATCHES4("ALTER", "INDEX", "", "RESET")) COMPLETE_WITH_CONST("("); /* ALTER INDEX SET|RESET ( */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "INDEX") == 0 && - (pg_strcasecmp(prev2_wd, "SET") == 0 || - pg_strcasecmp(prev2_wd, "RESET") == 0) && - pg_strcasecmp(prev_wd, "(") == 0) - { - static const char *const list_INDEXOPTIONS[] = - {"fillfactor", "fastupdate", "gin_pending_list_limit", NULL}; - - COMPLETE_WITH_LIST(list_INDEXOPTIONS); - } + else if (MATCHES5("ALTER", "INDEX", "", "SET|RESET", "(")) + COMPLETE_WITH_LIST3("fillfactor", "fastupdate", "gin_pending_list_limit"); /* ALTER LANGUAGE */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "LANGUAGE") == 0) - { - static const char *const list_ALTERLANGUAGE[] = - {"OWNER TO", "RENAME TO", NULL}; - - COMPLETE_WITH_LIST(list_ALTERLANGUAGE); - } + else if (MATCHES3("ALTER", "LANGUAGE", "")) + COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO"); /* ALTER LARGE OBJECT */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "LARGE") == 0 && - pg_strcasecmp(prev2_wd, "OBJECT") == 0) - { - static const char *const list_ALTERLARGEOBJECT[] = - {"OWNER TO", NULL}; - - COMPLETE_WITH_LIST(list_ALTERLARGEOBJECT); - } + else if (MATCHES4("ALTER", "LARGE", "OBJECT", "")) + COMPLETE_WITH_CONST("OWNER TO"); /* ALTER MATERIALIZED VIEW */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev_wd, "VIEW") == 0) - { + else if (MATCHES3("ALTER", "MATERIALIZED", "VIEW")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, "UNION SELECT 'ALL IN TABLESPACE'"); - } /* ALTER USER,ROLE */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - !(pg_strcasecmp(prev2_wd, "USER") == 0 && pg_strcasecmp(prev_wd, "MAPPING") == 0) && - (pg_strcasecmp(prev2_wd, "USER") == 0 || - pg_strcasecmp(prev2_wd, "ROLE") == 0)) + else if (MATCHES3("ALTER", "USER|ROLE", "") && !MATCHES2("USER", "MAPPING")) { static const char *const list_ALTERUSER[] = {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE", @@ -1250,10 +1302,7 @@ psql_completion(const char *text, int start, int end) } /* ALTER USER,ROLE WITH */ - else if ((pg_strcasecmp(prev4_wd, "ALTER") == 0 && - (pg_strcasecmp(prev3_wd, "USER") == 0 || - pg_strcasecmp(prev3_wd, "ROLE") == 0) && - pg_strcasecmp(prev_wd, "WITH") == 0)) + else if (MATCHES4("ALTER", "USER|ROLE", "", "WITH")) { /* Similar to the above, but don't complete "WITH" again. */ static const char *const list_ALTERUSER_WITH[] = @@ -1268,78 +1317,32 @@ psql_completion(const char *text, int start, int end) } /* complete ALTER USER,ROLE ENCRYPTED,UNENCRYPTED with PASSWORD */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - (pg_strcasecmp(prev3_wd, "ROLE") == 0 || pg_strcasecmp(prev3_wd, "USER") == 0) && - (pg_strcasecmp(prev_wd, "ENCRYPTED") == 0 || pg_strcasecmp(prev_wd, "UNENCRYPTED") == 0)) - { + else if (MATCHES4("ALTER", "USER|ROLE", "", "ENCRYPTED|UNENCRYPTED")) COMPLETE_WITH_CONST("PASSWORD"); - } /* ALTER DEFAULT PRIVILEGES */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "DEFAULT") == 0 && - pg_strcasecmp(prev_wd, "PRIVILEGES") == 0) - { - static const char *const list_ALTER_DEFAULT_PRIVILEGES[] = - {"FOR ROLE", "FOR USER", "IN SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTER_DEFAULT_PRIVILEGES); - } + else if (MATCHES3("ALTER", "DEFAULT", "PRIVILEGES")) + COMPLETE_WITH_LIST3("FOR ROLE", "FOR USER", "IN SCHEMA"); /* ALTER DEFAULT PRIVILEGES FOR */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "DEFAULT") == 0 && - pg_strcasecmp(prev2_wd, "PRIVILEGES") == 0 && - pg_strcasecmp(prev_wd, "FOR") == 0) - { - static const char *const list_ALTER_DEFAULT_PRIVILEGES_FOR[] = - {"ROLE", "USER", NULL}; - - COMPLETE_WITH_LIST(list_ALTER_DEFAULT_PRIVILEGES_FOR); - } + else if (MATCHES4("ALTER", "DEFAULT", "PRIVILEGES", "FOR")) + COMPLETE_WITH_LIST2("ROLE", "USER"); /* ALTER DEFAULT PRIVILEGES { FOR ROLE ... | IN SCHEMA ... } */ - else if (pg_strcasecmp(prev5_wd, "DEFAULT") == 0 && - pg_strcasecmp(prev4_wd, "PRIVILEGES") == 0 && - (pg_strcasecmp(prev3_wd, "FOR") == 0 || - pg_strcasecmp(prev3_wd, "IN") == 0)) - { - static const char *const list_ALTER_DEFAULT_PRIVILEGES_REST[] = - {"GRANT", "REVOKE", NULL}; - - COMPLETE_WITH_LIST(list_ALTER_DEFAULT_PRIVILEGES_REST); - } + else if (MATCHES5("DEFAULT", "PRIVILEGES", "FOR", "ROLE", "") || + MATCHES5("DEFAULT", "PRIVILEGES", "IN", "SCHEMA", "")) + COMPLETE_WITH_LIST2("GRANT", "REVOKE"); /* ALTER DOMAIN */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "DOMAIN") == 0) - { - static const char *const list_ALTERDOMAIN[] = - {"ADD", "DROP", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT", NULL}; - - COMPLETE_WITH_LIST(list_ALTERDOMAIN); - } + else if (MATCHES3("ALTER", "DOMAIN", "")) + COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT"); /* ALTER DOMAIN DROP */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "DOMAIN") == 0 && - pg_strcasecmp(prev_wd, "DROP") == 0) - { - static const char *const list_ALTERDOMAIN2[] = - {"CONSTRAINT", "DEFAULT", "NOT NULL", NULL}; - - COMPLETE_WITH_LIST(list_ALTERDOMAIN2); - } + else if (MATCHES4("ALTER", "DOMAIN", "", "DROP")) + COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL"); /* ALTER DOMAIN DROP|RENAME|VALIDATE CONSTRAINT */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "DOMAIN") == 0 && - (pg_strcasecmp(prev2_wd, "DROP") == 0 || - pg_strcasecmp(prev2_wd, "RENAME") == 0 || - pg_strcasecmp(prev2_wd, "VALIDATE") == 0) && - pg_strcasecmp(prev_wd, "CONSTRAINT") == 0) + else if (MATCHES5("ALTER", "DOMAIN", "", "DROP|RENAME|VALIDATE", "CONSTRAINT")) { completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_constraint_of_type); } /* ALTER DOMAIN RENAME */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "DOMAIN") == 0 && - pg_strcasecmp(prev_wd, "RENAME") == 0) + else if (MATCHES4("ALTER", "DOMAIN", "", "RENAME")) { static const char *const list_ALTERDOMAIN[] = {"CONSTRAINT", "TO", NULL}; @@ -1347,24 +1350,14 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_ALTERDOMAIN); } /* ALTER DOMAIN RENAME CONSTRAINT */ - else if (pg_strcasecmp(prev5_wd, "DOMAIN") == 0 && - pg_strcasecmp(prev3_wd, "RENAME") == 0 && - pg_strcasecmp(prev2_wd, "CONSTRAINT") == 0) + else if (MATCHES3("RENAME", "CONSTRAINT", "")) COMPLETE_WITH_CONST("TO"); /* ALTER DOMAIN SET */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "DOMAIN") == 0 && - pg_strcasecmp(prev_wd, "SET") == 0) - { - static const char *const list_ALTERDOMAIN3[] = - {"DEFAULT", "NOT NULL", "SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERDOMAIN3); - } + else if (MATCHES4("ALTER", "DOMAIN", "", "SET")) + COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA"); /* ALTER SEQUENCE */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "SEQUENCE") == 0) + else if (MATCHES3("ALTER", "SEQUENCE", "")) { static const char *const list_ALTERSEQUENCE[] = {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE", @@ -1373,123 +1366,63 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_ALTERSEQUENCE); } /* ALTER SEQUENCE NO */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "SEQUENCE") == 0 && - pg_strcasecmp(prev_wd, "NO") == 0) - { - static const char *const list_ALTERSEQUENCE2[] = - {"MINVALUE", "MAXVALUE", "CYCLE", NULL}; - - COMPLETE_WITH_LIST(list_ALTERSEQUENCE2); - } + else if (MATCHES4("ALTER", "SEQUEMCE", "", "NO")) + COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE"); /* ALTER SERVER */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "SERVER") == 0) - { - static const char *const list_ALTER_SERVER[] = - {"VERSION", "OPTIONS", "OWNER TO", NULL}; - - COMPLETE_WITH_LIST(list_ALTER_SERVER); - } + else if (MATCHES3("ALTER", "SERVER", "")) + COMPLETE_WITH_LIST3("VERSION", "OPTIONS", "OWNER TO"); /* ALTER SYSTEM SET, RESET, RESET ALL */ - else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && - pg_strcasecmp(prev_wd, "SYSTEM") == 0) - { - static const char *const list_ALTERSYSTEM[] = - {"SET", "RESET", NULL}; - - COMPLETE_WITH_LIST(list_ALTERSYSTEM); - } + else if (MATCHES2("ALTER", "SYSTEM")) + COMPLETE_WITH_LIST2("SET", "RESET"); /* ALTER SYSTEM SET|RESET */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "SYSTEM") == 0 && - (pg_strcasecmp(prev_wd, "SET") == 0 || - pg_strcasecmp(prev_wd, "RESET") == 0)) + else if (MATCHES4("ALTER", "SYSTEM", "SET|RESET", "")) COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars); /* ALTER VIEW */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "VIEW") == 0) - { - static const char *const list_ALTERVIEW[] = - {"ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERVIEW); - } + else if (MATCHES3("ALTER", "VIEW", "")) + COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA"); /* ALTER MATERIALIZED VIEW */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev2_wd, "VIEW") == 0) - { - static const char *const list_ALTERMATVIEW[] = - {"ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERMATVIEW); - } + else if (MATCHES4("ALTER", "MATERIALIZED", "VIEW", "")) + COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA"); /* ALTER POLICY ON */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "POLICY") == 0) + else if (MATCHES3("ALTER", "POLICY", "")) COMPLETE_WITH_CONST("ON"); /* ALTER POLICY ON */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "POLICY") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("ALTER", "POLICY", "", "ON")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* ALTER POLICY ON
- show options */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "POLICY") == 0 && - pg_strcasecmp(prev2_wd, "ON") == 0) - { - static const char *const list_ALTERPOLICY[] = - {"RENAME TO", "TO", "USING", "WITH CHECK", NULL}; - - COMPLETE_WITH_LIST(list_ALTERPOLICY); - } + else if (MATCHES5("ALTER", "POLICY", "", "ON", "
")) + COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING", "WITH CHECK"); /* ALTER POLICY ON
TO */ - else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 && - pg_strcasecmp(prev5_wd, "POLICY") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "TO") == 0) + else if (MATCHES6("ALTER", "POLICY", "", "ON", "
", "TO")) COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); /* ALTER POLICY ON
USING ( */ - else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 && - pg_strcasecmp(prev5_wd, "POLICY") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "USING") == 0) + else if (MATCHES6("ALTER", "POLICY", "", "ON", "
", "USING")) COMPLETE_WITH_CONST("("); /* ALTER POLICY ON
WITH CHECK ( */ - else if (pg_strcasecmp(prev6_wd, "POLICY") == 0 && - pg_strcasecmp(prev4_wd, "ON") == 0 && - pg_strcasecmp(prev2_wd, "WITH") == 0 && - pg_strcasecmp(prev_wd, "CHECK") == 0) + else if (MATCHES6("POLICY", "", "ON", "
", "WITH", "CHECK")) COMPLETE_WITH_CONST("("); /* ALTER RULE , add ON */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "RULE") == 0) + else if (MATCHES3("ALTER", "RULE", "")) COMPLETE_WITH_CONST("ON"); /* If we have ALTER RULE ON, then add the correct tablename */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "RULE") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("ALTER", "RULE", "", "ON")) { completion_info_charp = prev2_wd; COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule); } /* ALTER RULE ON */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "RULE") == 0) + else if (MATCHES5("ALTER", "RULE", "", "ON", "")) COMPLETE_WITH_CONST("RENAME TO"); /* ALTER TRIGGER , add ON */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "TRIGGER") == 0) + else if (MATCHES3("ALTER", "TRIGGER", "")) COMPLETE_WITH_CONST("ON"); - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TRIGGER") == 0) + else if (MATCHES4("ALTER", "TRIGGER", "", "")) { completion_info_charp = prev2_wd; COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger); @@ -1498,22 +1431,17 @@ psql_completion(const char *text, int start, int end) /* * If we have ALTER TRIGGER ON, then add the correct tablename */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("ALTER", "TRIGGER", "", "ON")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* ALTER TRIGGER ON */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TRIGGER") == 0 && - pg_strcasecmp(prev2_wd, "ON") == 0) + else if (MATCHES5("ALTER", "TRIGGER", "", "ON", "")) COMPLETE_WITH_CONST("RENAME TO"); /* * If we detect ALTER TABLE , suggest sub commands */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "TABLE") == 0) + else if (MATCHES3("ALTER", "TABLE", "")) { static const char *const list_ALTER2[] = {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT", @@ -1523,279 +1451,144 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_ALTER2); } /* ALTER TABLE xxx ENABLE */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "ENABLE") == 0) + else if (MATCHES4("ALTER", "TABLE", "", "ENABLE")) { static const char *const list_ALTERENABLE[] = {"ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE", "TRIGGER", NULL}; COMPLETE_WITH_LIST(list_ALTERENABLE); } - else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "ENABLE") == 0 && - (pg_strcasecmp(prev_wd, "REPLICA") == 0 || - pg_strcasecmp(prev_wd, "ALWAYS") == 0)) + else if (MATCHES4("TABLE", "", "ENABLE", "REPLICA|ALWAYS")) { static const char *const list_ALTERENABLE2[] = {"RULE", "TRIGGER", NULL}; COMPLETE_WITH_LIST(list_ALTERENABLE2); } - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "ENABLE") == 0 && - pg_strcasecmp(prev_wd, "RULE") == 0) + else if (MATCHES5("ALTER", "TABLE", "", "ENABLE", "RULE")) { completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_rule_of_table); } - else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 && - pg_strcasecmp(prev5_wd, "TABLE") == 0 && - pg_strcasecmp(prev3_wd, "ENABLE") == 0 && - pg_strcasecmp(prev_wd, "RULE") == 0) + else if (MATCHES6("ALTER", "TABLE", "", "ENABLE", "", "RULE")) { completion_info_charp = prev4_wd; COMPLETE_WITH_QUERY(Query_for_rule_of_table); } - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "ENABLE") == 0 && - pg_strcasecmp(prev_wd, "TRIGGER") == 0) + else if (MATCHES5("ALTER", "TABLE", "", "ENABLE", "TRIGGER")) { completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_trigger_of_table); } - else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 && - pg_strcasecmp(prev5_wd, "TABLE") == 0 && - pg_strcasecmp(prev3_wd, "ENABLE") == 0 && - pg_strcasecmp(prev_wd, "TRIGGER") == 0) + else if (MATCHES6("ALTER", "TABLE", "", "ENABLE", "", "TRIGGER")) { completion_info_charp = prev4_wd; COMPLETE_WITH_QUERY(Query_for_trigger_of_table); } /* ALTER TABLE xxx INHERIT */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "INHERIT") == 0) - { + else if (MATCHES4("ALTER", "TABLE", "", "INHERIT")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, ""); - } /* ALTER TABLE xxx NO INHERIT */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "NO") == 0 && - pg_strcasecmp(prev_wd, "INHERIT") == 0) - { + else if (MATCHES5("ALTER", "TABLE", "", "NO", "INHERIT")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, ""); - } /* ALTER TABLE xxx DISABLE */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "DISABLE") == 0) - { - static const char *const list_ALTERDISABLE[] = - {"ROW LEVEL SECURITY", "RULE", "TRIGGER", NULL}; - - COMPLETE_WITH_LIST(list_ALTERDISABLE); - } - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "DISABLE") == 0 && - pg_strcasecmp(prev_wd, "RULE") == 0) + else if (MATCHES4("ALTER", "TABLE", "", "DISABLE")) + COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER"); + else if (MATCHES5("ALTER", "TABLE", "", "DISABLE", "RULE")) { completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_rule_of_table); } - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "DISABLE") == 0 && - pg_strcasecmp(prev_wd, "TRIGGER") == 0) + else if (MATCHES5("ALTER", "TABLE", "", "DISABLE", "TRIGGER")) { completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_trigger_of_table); } - else if (pg_strcasecmp(prev4_wd, "DISABLE") == 0 && - pg_strcasecmp(prev3_wd, "ROW") == 0 && - pg_strcasecmp(prev2_wd, "LEVEL") == 0 && - pg_strcasecmp(prev_wd, "SECURITY") == 0) - { - static const char *const list_DISABLERLS[] = - {"CASCADE", NULL}; - - COMPLETE_WITH_LIST(list_DISABLERLS); - } + else if (MATCHES4("DISABLE", "ROW", "LEVEL", "SECURITY")) + COMPLETE_WITH_CONST("CASCADE"); /* ALTER TABLE xxx ALTER */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "ALTER") == 0) + else if (MATCHES4("ALTER", "TABLE", "", "ALTER")) COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'"); /* ALTER TABLE xxx RENAME */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "RENAME") == 0) + else if (MATCHES4("ALTER", "TABLE", "", "RENAME")) COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'"); /* * If we have TABLE ALTER COLUMN|RENAME COLUMN, provide list of * columns */ - else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - (pg_strcasecmp(prev2_wd, "ALTER") == 0 || - pg_strcasecmp(prev2_wd, "RENAME") == 0) && - pg_strcasecmp(prev_wd, "COLUMN") == 0) + else if (MATCHES4("TABLE", "", "ALTER|RENAME", "COLUMN")) COMPLETE_WITH_ATTR(prev3_wd, ""); /* ALTER TABLE xxx RENAME yyy */ - else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "RENAME") == 0 && - pg_strcasecmp(prev_wd, "CONSTRAINT") != 0 && - pg_strcasecmp(prev_wd, "TO") != 0) + else if (MATCHES5("ALTER", "TABLE", "", "RENAME", "") && + !MATCHES1("CONSTRAINT|TO")) COMPLETE_WITH_CONST("TO"); /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */ - else if (pg_strcasecmp(prev5_wd, "TABLE") == 0 && - pg_strcasecmp(prev3_wd, "RENAME") == 0 && - (pg_strcasecmp(prev2_wd, "COLUMN") == 0 || - pg_strcasecmp(prev2_wd, "CONSTRAINT") == 0) && - pg_strcasecmp(prev_wd, "TO") != 0) + else if (MATCHES6("ALTER", "TABLE", "", "RENAME", "COLUMN|CONSTRAINT", "") && + !MATCHES1("TO")) COMPLETE_WITH_CONST("TO"); /* If we have TABLE DROP, provide COLUMN or CONSTRAINT */ - else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "DROP") == 0) - { - static const char *const list_TABLEDROP[] = - {"COLUMN", "CONSTRAINT", NULL}; - - COMPLETE_WITH_LIST(list_TABLEDROP); - } + else if (MATCHES3("TABLE", "", "DROP")) + COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT"); /* If we have ALTER TABLE DROP COLUMN, provide list of columns */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "DROP") == 0 && - pg_strcasecmp(prev_wd, "COLUMN") == 0) + else if (MATCHES5("ALTER", "TABLE", "", "DROP", "COLUMN")) COMPLETE_WITH_ATTR(prev3_wd, ""); /* * If we have ALTER TABLE ALTER|DROP|RENAME|VALIDATE CONSTRAINT, * provide list of constraints */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TABLE") == 0 && - (pg_strcasecmp(prev2_wd, "ALTER") == 0 || - pg_strcasecmp(prev2_wd, "DROP") == 0 || - pg_strcasecmp(prev2_wd, "RENAME") == 0 || - pg_strcasecmp(prev2_wd, "VALIDATE") == 0) && - pg_strcasecmp(prev_wd, "CONSTRAINT") == 0) + else if (MATCHES5("ALTER", "TABLE", "", "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT")) { completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_constraint_of_table); } /* ALTER TABLE ALTER [COLUMN] */ - else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "COLUMN") == 0) || - (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "ALTER") == 0)) - { - static const char *const list_COLUMNALTER[] = - {"TYPE", "SET", "RESET", "DROP", NULL}; - - COMPLETE_WITH_LIST(list_COLUMNALTER); - } + else if (MATCHES3("ALTER", "COLUMN", "") || + MATCHES4("TABLE", "", "ALTER", "")) + COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP"); /* ALTER TABLE ALTER [COLUMN] SET */ - else if (((pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "COLUMN") == 0) || - (pg_strcasecmp(prev5_wd, "TABLE") == 0 && - pg_strcasecmp(prev3_wd, "ALTER") == 0)) && - pg_strcasecmp(prev_wd, "SET") == 0) - { - static const char *const list_COLUMNSET[] = - {"(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE", NULL}; - - COMPLETE_WITH_LIST(list_COLUMNSET); - } + else if (MATCHES4("ALTER", "COLUMN", "", "SET") || + MATCHES5("TABLE", "", "ALTER", "", "SET")) + COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE"); /* ALTER TABLE ALTER [COLUMN] SET ( */ - else if (((pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "COLUMN") == 0) || - pg_strcasecmp(prev4_wd, "ALTER") == 0) && - pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev_wd, "(") == 0) - { - static const char *const list_COLUMNOPTIONS[] = - {"n_distinct", "n_distinct_inherited", NULL}; - - COMPLETE_WITH_LIST(list_COLUMNOPTIONS); - } + else if (MATCHES5("ALTER", "COLUMN", "", "SET", "(") || + MATCHES4("ALTER", "", "SET", "(")) + COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited"); /* ALTER TABLE ALTER [COLUMN] SET STORAGE */ - else if (((pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "COLUMN") == 0) || - pg_strcasecmp(prev4_wd, "ALTER") == 0) && - pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev_wd, "STORAGE") == 0) - { - static const char *const list_COLUMNSTORAGE[] = - {"PLAIN", "EXTERNAL", "EXTENDED", "MAIN", NULL}; - - COMPLETE_WITH_LIST(list_COLUMNSTORAGE); - } + else if (MATCHES5("ALTER", "COLUMN", "", "SET", "STORAGE") || + MATCHES4("ALTER", "", "SET", "STORAGE")) + COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN"); /* ALTER TABLE ALTER [COLUMN] DROP */ - else if (((pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "COLUMN") == 0) || - (pg_strcasecmp(prev5_wd, "TABLE") == 0 && - pg_strcasecmp(prev3_wd, "ALTER") == 0)) && - pg_strcasecmp(prev_wd, "DROP") == 0) - { - static const char *const list_COLUMNDROP[] = - {"DEFAULT", "NOT NULL", NULL}; - - COMPLETE_WITH_LIST(list_COLUMNDROP); - } - else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "CLUSTER") == 0) + else if (MATCHES4("ALTER", "COLUMN", "", "DROP") || + MATCHES5("TABLE", "", "ALTER", "", "DROP")) + COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL"); + else if (MATCHES3("TABLE", "", "CLUSTER")) COMPLETE_WITH_CONST("ON"); - else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "CLUSTER") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("TABLE", "", "CLUSTER", "ON")) { completion_info_charp = prev3_wd; COMPLETE_WITH_QUERY(Query_for_index_of_table); } /* If we have TABLE SET, provide list of attributes and '(' */ - else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "SET") == 0) - { - static const char *const list_TABLESET[] = - {"(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT", NULL}; - - COMPLETE_WITH_LIST(list_TABLESET); - } + else if (MATCHES3("TABLE", "", "SET")) + COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT"); /* If we have TABLE SET TABLESPACE provide a list of tablespaces */ - else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev_wd, "TABLESPACE") == 0) + else if (MATCHES4("TABLE", "", "SET", "TABLESPACE")) COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); /* If we have TABLE SET WITHOUT provide CLUSTER or OIDS */ - else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev_wd, "WITHOUT") == 0) - { - static const char *const list_TABLESET2[] = - {"CLUSTER", "OIDS", NULL}; - - COMPLETE_WITH_LIST(list_TABLESET2); - } + else if (MATCHES4("TABLE", "", "SET", "WITHOUT")) + COMPLETE_WITH_LIST2("CLUSTER", "OIDS"); /* ALTER TABLE RESET */ - else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "RESET") == 0) + else if (MATCHES3("TABLE", "", "RESET")) COMPLETE_WITH_CONST("("); /* ALTER TABLE SET|RESET ( */ - else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - (pg_strcasecmp(prev2_wd, "SET") == 0 || - pg_strcasecmp(prev2_wd, "RESET") == 0) && - pg_strcasecmp(prev_wd, "(") == 0) + else if (MATCHES4("TBALE", "", "SET|RESET", "(")) { static const char *const list_TABLEOPTIONS[] = { @@ -1832,246 +1625,109 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_TABLEOPTIONS); } - else if (pg_strcasecmp(prev4_wd, "REPLICA") == 0 && - pg_strcasecmp(prev3_wd, "IDENTITY") == 0 && - pg_strcasecmp(prev2_wd, "USING") == 0 && - pg_strcasecmp(prev_wd, "INDEX") == 0) + else if (MATCHES4("REPLICA", "IDENTITY", "USING", "INDEX")) { completion_info_charp = prev5_wd; COMPLETE_WITH_QUERY(Query_for_index_of_table); } - else if (pg_strcasecmp(prev5_wd, "TABLE") == 0 && - pg_strcasecmp(prev3_wd, "REPLICA") == 0 && - pg_strcasecmp(prev2_wd, "IDENTITY") == 0 && - pg_strcasecmp(prev_wd, "USING") == 0) - { + else if (MATCHES5("TABLE", "", "REPLICA", "IDENTITY", "USING")) COMPLETE_WITH_CONST("INDEX"); - } - else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "REPLICA") == 0 && - pg_strcasecmp(prev_wd, "IDENTITY") == 0) - { - static const char *const list_REPLICAID[] = - {"FULL", "NOTHING", "DEFAULT", "USING", NULL}; - - COMPLETE_WITH_LIST(list_REPLICAID); - } - else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev_wd, "REPLICA") == 0) - { + else if (MATCHES4("TABLE", "", "REPLICA", "IDENTITY")) + COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING"); + else if (MATCHES3("TABLE", "", "REPLICA")) COMPLETE_WITH_CONST("IDENTITY"); - } /* ALTER TABLESPACE with RENAME TO, OWNER TO, SET, RESET */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "TABLESPACE") == 0) - { - static const char *const list_ALTERTSPC[] = - {"RENAME TO", "OWNER TO", "SET", "RESET", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTSPC); - } + else if (MATCHES3("ALTER", "TABLESPACE", "")) + COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET"); /* ALTER TABLESPACE SET|RESET */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TABLESPACE") == 0 && - (pg_strcasecmp(prev_wd, "SET") == 0 || - pg_strcasecmp(prev_wd, "RESET") == 0)) + else if (MATCHES4("ALTER", "TABLESPACE", "", "SET|RESET")) COMPLETE_WITH_CONST("("); /* ALTER TABLESPACE SET|RESET ( */ - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TABLESPACE") == 0 && - (pg_strcasecmp(prev2_wd, "SET") == 0 || - pg_strcasecmp(prev2_wd, "RESET") == 0) && - pg_strcasecmp(prev_wd, "(") == 0) - { - static const char *const list_TABLESPACEOPTIONS[] = - {"seq_page_cost", "random_page_cost", NULL}; - - COMPLETE_WITH_LIST(list_TABLESPACEOPTIONS); - } + else if (MATCHES5("ALTER", "TABLESPACE", "", "SET|RESET", "(")) + COMPLETE_WITH_LIST2("seq_page_cost", "random_page_cost"); /* ALTER TEXT SEARCH */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "TEXT") == 0 && - pg_strcasecmp(prev_wd, "SEARCH") == 0) - { - static const char *const list_ALTERTEXTSEARCH[] = - {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH); - } - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TEXT") == 0 && - pg_strcasecmp(prev3_wd, "SEARCH") == 0 && - (pg_strcasecmp(prev2_wd, "TEMPLATE") == 0 || - pg_strcasecmp(prev2_wd, "PARSER") == 0)) - { - static const char *const list_ALTERTEXTSEARCH2[] = - {"RENAME TO", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH2); - } - - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TEXT") == 0 && - pg_strcasecmp(prev3_wd, "SEARCH") == 0 && - pg_strcasecmp(prev2_wd, "DICTIONARY") == 0) - { - static const char *const list_ALTERTEXTSEARCH3[] = - {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3); - } - - else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && - pg_strcasecmp(prev4_wd, "TEXT") == 0 && - pg_strcasecmp(prev3_wd, "SEARCH") == 0 && - pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0) - { - static const char *const list_ALTERTEXTSEARCH4[] = - {"ADD MAPPING FOR", "ALTER MAPPING", "DROP MAPPING FOR", "OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH4); - } + else if (MATCHES3("ALTER", "TEXT", "SEARCH")) + COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE"); + else if (MATCHES5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", "")) + COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA"); + else if (MATCHES5("ALTER", "TEXT", "SEARCH", "DICTIONARY", "")) + COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA"); + else if (MATCHES5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", "")) + COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING", "DROP MAPPING FOR", + "OWNER TO", "RENAME TO", "SET SCHEMA"); /* complete ALTER TYPE with actions */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "TYPE") == 0) - { - static const char *const list_ALTERTYPE[] = - {"ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE", "DROP ATTRIBUTE", - "OWNER TO", "RENAME", "SET SCHEMA", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTYPE); - } + else if (MATCHES3("ALTER", "TYPE", "")) + COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE", + "DROP ATTRIBUTE", "OWNER TO", "RENAME", "SET SCHEMA"); /* complete ALTER TYPE ADD with actions */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TYPE") == 0 && - pg_strcasecmp(prev_wd, "ADD") == 0) - { - static const char *const list_ALTERTYPE[] = - {"ATTRIBUTE", "VALUE", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTYPE); - } + else if (MATCHES4("ALTER", "TYPE", "", "ADD")) + COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE"); /* ALTER TYPE RENAME */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "TYPE") == 0 && - pg_strcasecmp(prev_wd, "RENAME") == 0) - { - static const char *const list_ALTERTYPE[] = - {"ATTRIBUTE", "TO", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTYPE); - } + else if (MATCHES4("ALTER", "TYPE", "", "RENAME")) + COMPLETE_WITH_LIST2("ATTRIBUTE", "TO"); /* ALTER TYPE xxx RENAME ATTRIBUTE yyy */ - else if (pg_strcasecmp(prev5_wd, "TYPE") == 0 && - pg_strcasecmp(prev3_wd, "RENAME") == 0 && - pg_strcasecmp(prev2_wd, "ATTRIBUTE") == 0) + else if (MATCHES5("TYPE", "", "RENAME", "ATTRIBUTE", "")) COMPLETE_WITH_CONST("TO"); /* * If we have TYPE ALTER/DROP/RENAME ATTRIBUTE, provide list of * attributes */ - else if (pg_strcasecmp(prev4_wd, "TYPE") == 0 && - (pg_strcasecmp(prev2_wd, "ALTER") == 0 || - pg_strcasecmp(prev2_wd, "DROP") == 0 || - pg_strcasecmp(prev2_wd, "RENAME") == 0) && - pg_strcasecmp(prev_wd, "ATTRIBUTE") == 0) + else if (MATCHES4("TYPE", "", "ALTER|DROP|RENAME", "ATTRIBUTE")) COMPLETE_WITH_ATTR(prev3_wd, ""); /* ALTER TYPE ALTER ATTRIBUTE */ - else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "ATTRIBUTE") == 0)) - { + else if (MATCHES3("ALTER", "ATTRIBUTE", "")) COMPLETE_WITH_CONST("TYPE"); - } /* complete ALTER GROUP */ - else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && - pg_strcasecmp(prev2_wd, "GROUP") == 0) - { - static const char *const list_ALTERGROUP[] = - {"ADD USER", "DROP USER", "RENAME TO", NULL}; - - COMPLETE_WITH_LIST(list_ALTERGROUP); - } + else if (MATCHES3("ALTER", "GROUP", "")) + COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO"); /* complete ALTER GROUP ADD|DROP with USER */ - else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && - pg_strcasecmp(prev3_wd, "GROUP") == 0 && - (pg_strcasecmp(prev_wd, "ADD") == 0 || - pg_strcasecmp(prev_wd, "DROP") == 0)) + else if (MATCHES4("ALTER", "GROUP", "", "ADD|DROP")) COMPLETE_WITH_CONST("USER"); /* complete {ALTER} GROUP ADD|DROP USER with a user name */ - else if (pg_strcasecmp(prev4_wd, "GROUP") == 0 && - (pg_strcasecmp(prev2_wd, "ADD") == 0 || - pg_strcasecmp(prev2_wd, "DROP") == 0) && - pg_strcasecmp(prev_wd, "USER") == 0) + else if (MATCHES4("GROUP", "", "ADD|DROP", "USER")) COMPLETE_WITH_QUERY(Query_for_list_of_roles); /* BEGIN, END, ABORT */ - else if (pg_strcasecmp(prev_wd, "BEGIN") == 0 || - pg_strcasecmp(prev_wd, "END") == 0 || - pg_strcasecmp(prev_wd, "ABORT") == 0) - { - static const char *const list_TRANS[] = - {"WORK", "TRANSACTION", NULL}; - - COMPLETE_WITH_LIST(list_TRANS); - } + else if (MATCHES1("BEGIN|END|ABORT")) + COMPLETE_WITH_LIST2("WORK", "TRANSACTION"); /* COMMIT */ - else if (pg_strcasecmp(prev_wd, "COMMIT") == 0) - { - static const char *const list_COMMIT[] = - {"WORK", "TRANSACTION", "PREPARED", NULL}; - - COMPLETE_WITH_LIST(list_COMMIT); - } + else if (MATCHES1("COMMIT")) + COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED"); /* RELEASE SAVEPOINT */ - else if (pg_strcasecmp(prev_wd, "RELEASE") == 0) + else if (MATCHES1("RELEASE")) COMPLETE_WITH_CONST("SAVEPOINT"); /* ROLLBACK*/ - else if (pg_strcasecmp(prev_wd, "ROLLBACK") == 0) - { - static const char *const list_TRANS[] = - {"WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED", NULL}; - - COMPLETE_WITH_LIST(list_TRANS); - } + else if (MATCHES1("ROLLBACK")) + COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED"); /* CLUSTER */ /* * If the previous word is CLUSTER and not WITHOUT produce list of tables */ - else if (pg_strcasecmp(prev_wd, "CLUSTER") == 0 && - pg_strcasecmp(prev2_wd, "WITHOUT") != 0) + else if (MATCHES1("CLUSTER") && !MATCHES2("WITHOUT", "CLUSTER")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'"); /* * If the previous words are CLUSTER VERBOSE produce list of tables */ - else if (pg_strcasecmp(prev_wd, "VERBOSE") == 0 && - pg_strcasecmp(prev2_wd, "CLUSTER") == 0) + else if (MATCHES2("CLUSTER", "VERBOSE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL); /* If we have CLUSTER , then add "USING" */ - else if (pg_strcasecmp(prev2_wd, "CLUSTER") == 0 && - pg_strcasecmp(prev_wd, "ON") != 0 && - pg_strcasecmp(prev_wd, "VERBOSE") != 0) - { + else if (MATCHES2("CLUSTER", "") && !MATCHES1("VERBOSE")) COMPLETE_WITH_CONST("USING"); - } /* If we have CLUSTER VERBOSE , then add "USING" */ - else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 && - pg_strcasecmp(prev2_wd, "VERBOSE") == 0) - { + else if (MATCHES3("CLUSTER", "VERBOSE", "")) COMPLETE_WITH_CONST("USING"); - } /* * If we have CLUSTER USING, then add the index as well. */ - else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 && - pg_strcasecmp(prev_wd, "USING") == 0) + else if (MATCHES3("CLUSTER", "", "USING")) { completion_info_charp = prev2_wd; COMPLETE_WITH_QUERY(Query_for_index_of_table); @@ -2080,19 +1736,16 @@ psql_completion(const char *text, int start, int end) /* * If we have CLUSTER VERBOSE USING, then add the index as well. */ - else if (pg_strcasecmp(prev4_wd, "CLUSTER") == 0 && - pg_strcasecmp(prev3_wd, "VERBOSE") == 0 && - pg_strcasecmp(prev_wd, "USING") == 0) + else if (MATCHES4("CLUSTER", "VERBOSE", "", "USING")) { completion_info_charp = prev2_wd; COMPLETE_WITH_QUERY(Query_for_index_of_table); } /* COMMENT */ - else if (pg_strcasecmp(prev_wd, "COMMENT") == 0) + else if (MATCHES1("COMMENT")) COMPLETE_WITH_CONST("ON"); - else if (pg_strcasecmp(prev2_wd, "COMMENT") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES2("COMMENT", "ON")) { static const char *const list_COMMENT[] = {"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION", @@ -2104,66 +1757,27 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_COMMENT); } - else if (pg_strcasecmp(prev3_wd, "COMMENT") == 0 && - pg_strcasecmp(prev2_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "FOREIGN") == 0) - { - static const char *const list_TRANS2[] = - {"DATA WRAPPER", "TABLE", NULL}; - - COMPLETE_WITH_LIST(list_TRANS2); - } - else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev2_wd, "TEXT") == 0 && - pg_strcasecmp(prev_wd, "SEARCH") == 0) - { - static const char *const list_TRANS2[] = - {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL}; - - COMPLETE_WITH_LIST(list_TRANS2); - } - else if (pg_strcasecmp(prev3_wd, "COMMENT") == 0 && - pg_strcasecmp(prev2_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "CONSTRAINT") == 0) - { + 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); - } - else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev2_wd, "CONSTRAINT") == 0) - { + else if (MATCHES4("COMMENT", "ON", "CONSTRAINT", "")) COMPLETE_WITH_CONST("ON"); - } - else if (pg_strcasecmp(prev5_wd, "COMMENT") == 0 && - pg_strcasecmp(prev4_wd, "ON") == 0 && - pg_strcasecmp(prev3_wd, "CONSTRAINT") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES5("COMMENT", "ON", "CONSTRAINT", "", "ON")) { completion_info_charp = prev2_wd; COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint); } - else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev2_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev_wd, "VIEW") == 0) - { + else if (MATCHES4("COMMENT", "ON", "MATERIALIZED", "VIEW")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); - } - else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev2_wd, "EVENT") == 0 && - pg_strcasecmp(prev_wd, "TRIGGER") == 0) - { + else if (MATCHES4("COMMENT", "ON", "EVENT", "TRIGGER")) COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers); - } - else if (((pg_strcasecmp(prev4_wd, "COMMENT") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0) || - (pg_strcasecmp(prev5_wd, "COMMENT") == 0 && - pg_strcasecmp(prev4_wd, "ON") == 0) || - (pg_strcasecmp(prev6_wd, "COMMENT") == 0 && - pg_strcasecmp(prev5_wd, "ON") == 0)) && - pg_strcasecmp(prev_wd, "IS") != 0) + else if ((MATCHES4("COMMENT", "ON", "", "") || + MATCHES5("COMMENT", "ON", "", "", "") || + MATCHES6("COMMENT", "ON", "", "", "", "")) && + !MATCHES1("IS")) COMPLETE_WITH_CONST("IS"); /* COPY */ @@ -2172,59 +1786,28 @@ psql_completion(const char *text, int start, int end) * If we have COPY [BINARY] (which you'd have to type yourself), offer * list of tables (Also cover the analogous backslash command) */ - else if (pg_strcasecmp(prev_wd, "COPY") == 0 || - pg_strcasecmp(prev_wd, "\\copy") == 0 || - (pg_strcasecmp(prev2_wd, "COPY") == 0 && - pg_strcasecmp(prev_wd, "BINARY") == 0)) + else if (MATCHES1("COPY|\\copy") || MATCHES2("COPY", "BINARY")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* If we have COPY|BINARY , complete it with "TO" or "FROM" */ - else if (pg_strcasecmp(prev2_wd, "COPY") == 0 || - pg_strcasecmp(prev2_wd, "\\copy") == 0 || - pg_strcasecmp(prev2_wd, "BINARY") == 0) - { - static const char *const list_FROMTO[] = - {"FROM", "TO", NULL}; - - COMPLETE_WITH_LIST(list_FROMTO); - } + else if (MATCHES2("COPY|\\copy|BINARY", "")) + COMPLETE_WITH_LIST2("FROM", "TO"); /* If we have COPY|BINARY FROM|TO, complete with filename */ - else if ((pg_strcasecmp(prev3_wd, "COPY") == 0 || - pg_strcasecmp(prev3_wd, "\\copy") == 0 || - pg_strcasecmp(prev3_wd, "BINARY") == 0) && - (pg_strcasecmp(prev_wd, "FROM") == 0 || - pg_strcasecmp(prev_wd, "TO") == 0)) + else if (MATCHES3("COPY|\\copy|BINARY", "", "FROM|TO")) { completion_charp = ""; matches = completion_matches(text, complete_from_files); } /* Handle COPY|BINARY FROM|TO filename */ - else if ((pg_strcasecmp(prev4_wd, "COPY") == 0 || - pg_strcasecmp(prev4_wd, "\\copy") == 0 || - pg_strcasecmp(prev4_wd, "BINARY") == 0) && - (pg_strcasecmp(prev2_wd, "FROM") == 0 || - pg_strcasecmp(prev2_wd, "TO") == 0)) - { - static const char *const list_COPY[] = - {"BINARY", "OIDS", "DELIMITER", "NULL", "CSV", "ENCODING", NULL}; - - COMPLETE_WITH_LIST(list_COPY); - } + else if (MATCHES4("COPY|\\copy|BINARY", "", "FROM|TO", "")) + COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV", "ENCODING"); /* Handle COPY|BINARY FROM|TO filename CSV */ - else if (pg_strcasecmp(prev_wd, "CSV") == 0 && - (pg_strcasecmp(prev3_wd, "FROM") == 0 || - pg_strcasecmp(prev3_wd, "TO") == 0)) - { - static const char *const list_CSV[] = - {"HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE", "FORCE NOT NULL", NULL}; - - COMPLETE_WITH_LIST(list_CSV); - } + else if (MATCHES3("FROM|TO", "", "CSV")) + COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE", "FORCE NOT NULL"); /* CREATE DATABASE */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "DATABASE") == 0) + else if (MATCHES3("CREATE", "DATABASE", "")) { static const char *const list_DATABASE[] = {"OWNER", "TEMPLATE", "ENCODING", "TABLESPACE", "IS_TEMPLATE", @@ -2234,403 +1817,194 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_DATABASE); } - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "DATABASE") == 0 && - pg_strcasecmp(prev_wd, "TEMPLATE") == 0) + else if (MATCHES4("CREATE", "DATABASE", "", "TEMPLATE")) COMPLETE_WITH_QUERY(Query_for_list_of_template_databases); /* CREATE EXTENSION */ /* Complete with available extensions rather than installed ones. */ - else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && - pg_strcasecmp(prev_wd, "EXTENSION") == 0) + else if (MATCHES2("CREATE", "EXTENSION")) COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions); /* CREATE EXTENSION */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "EXTENSION") == 0) + else if (MATCHES3("CREATE", "EXTENSION", "")) COMPLETE_WITH_CONST("WITH SCHEMA"); /* CREATE FOREIGN */ - else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && - pg_strcasecmp(prev_wd, "FOREIGN") == 0) - { - static const char *const list_CREATE_FOREIGN[] = - {"DATA WRAPPER", "TABLE", NULL}; - - COMPLETE_WITH_LIST(list_CREATE_FOREIGN); - } + else if (MATCHES2("CREATE", "FOREIGN")) + COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE"); /* CREATE FOREIGN DATA WRAPPER */ - else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && - pg_strcasecmp(prev4_wd, "FOREIGN") == 0 && - pg_strcasecmp(prev3_wd, "DATA") == 0 && - pg_strcasecmp(prev2_wd, "WRAPPER") == 0) - { - static const char *const list_CREATE_FOREIGN_DATA_WRAPPER[] = - {"HANDLER", "VALIDATOR", NULL}; - - COMPLETE_WITH_LIST(list_CREATE_FOREIGN_DATA_WRAPPER); - } + else if (MATCHES5("CREATE", "FOREIGN", "DATA", "WRAPPER", "")) + COMPLETE_WITH_LIST2("HANDLER", "VALIDATOR"); /* CREATE INDEX */ /* First off we complete CREATE UNIQUE with "INDEX" */ - else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && - pg_strcasecmp(prev_wd, "UNIQUE") == 0) + else if (MATCHES2("CREATE", "UNIQUE")) COMPLETE_WITH_CONST("INDEX"); /* If we have CREATE|UNIQUE INDEX, then add "ON" and existing indexes */ - else if (pg_strcasecmp(prev_wd, "INDEX") == 0 && - (pg_strcasecmp(prev2_wd, "CREATE") == 0 || - pg_strcasecmp(prev2_wd, "UNIQUE") == 0)) + else if (MATCHES2("CREATE|UNIQUE", "INDEX")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, " UNION SELECT 'ON'" " UNION SELECT 'CONCURRENTLY'"); /* Complete ... INDEX [] ON with a list of tables */ - else if ((pg_strcasecmp(prev3_wd, "INDEX") == 0 || - pg_strcasecmp(prev2_wd, "INDEX") == 0 || - pg_strcasecmp(prev2_wd, "CONCURRENTLY") == 0) && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES3("INDEX", "", "ON") || + MATCHES2("INDEX|CONCURRENTLY", "ON")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL); /* If we have CREATE|UNIQUE INDEX CONCURRENTLY, then add "ON" */ - else if ((pg_strcasecmp(prev3_wd, "INDEX") == 0 || - pg_strcasecmp(prev2_wd, "INDEX") == 0) && - pg_strcasecmp(prev_wd, "CONCURRENTLY") == 0) + else if (MATCHES3("INDEX", "", "CONCURRENTLY") || + MATCHES2("INDEX", "CONCURRENTLY")) COMPLETE_WITH_CONST("ON"); /* If we have CREATE|UNIQUE INDEX , then add "ON" or "CONCURRENTLY" */ - else if ((pg_strcasecmp(prev3_wd, "CREATE") == 0 || - pg_strcasecmp(prev3_wd, "UNIQUE") == 0) && - pg_strcasecmp(prev2_wd, "INDEX") == 0) - { - static const char *const list_CREATE_INDEX[] = - {"CONCURRENTLY", "ON", NULL}; - - COMPLETE_WITH_LIST(list_CREATE_INDEX); - } + else if (MATCHES3("CREATE|UNIQUE", "INDEX", "")) + COMPLETE_WITH_LIST2("CONCURRENTLY", "ON"); /* * Complete INDEX ON
with a list of table columns (which * should really be in parens) */ - else if ((pg_strcasecmp(prev4_wd, "INDEX") == 0 || - pg_strcasecmp(prev3_wd, "INDEX") == 0 || - pg_strcasecmp(prev3_wd, "CONCURRENTLY") == 0) && - pg_strcasecmp(prev2_wd, "ON") == 0) - { - static const char *const list_CREATE_INDEX2[] = - {"(", "USING", NULL}; - - COMPLETE_WITH_LIST(list_CREATE_INDEX2); - } - else if ((pg_strcasecmp(prev5_wd, "INDEX") == 0 || - pg_strcasecmp(prev4_wd, "INDEX") == 0 || - pg_strcasecmp(prev4_wd, "CONCURRENTLY") == 0) && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "(") == 0) + else if (MATCHES4("INDEX", "", "ON", "") || + MATCHES3("INDEX|CONCURRENTLY", "ON", "")) + COMPLETE_WITH_LIST2("(", "USING"); + else if (MATCHES5("INDEX", "", "ON", "", "(") || + MATCHES4("INDEX|CONCURRENTLY", "ON", "", "(")) COMPLETE_WITH_ATTR(prev2_wd, ""); /* same if you put in USING */ - else if (pg_strcasecmp(prev5_wd, "ON") == 0 && - pg_strcasecmp(prev3_wd, "USING") == 0 && - pg_strcasecmp(prev_wd, "(") == 0) + else if (MATCHES5("ON", "", "USING", "", "(")) COMPLETE_WITH_ATTR(prev4_wd, ""); /* Complete USING with an index method */ - else if ((pg_strcasecmp(prev6_wd, "INDEX") == 0 || - pg_strcasecmp(prev5_wd, "INDEX") == 0 || - pg_strcasecmp(prev4_wd, "INDEX") == 0) && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "USING") == 0) + else if (MATCHES6("INDEX", "", "", "ON", "", "USING") || + MATCHES5("INDEX", "", "ON", "", "USING") || + MATCHES4("INDEX", "ON", "", "USING")) COMPLETE_WITH_QUERY(Query_for_list_of_access_methods); - else if (pg_strcasecmp(prev4_wd, "ON") == 0 && - (!(pg_strcasecmp(prev6_wd, "POLICY") == 0) && - !(pg_strcasecmp(prev4_wd, "FOR") == 0)) && - pg_strcasecmp(prev2_wd, "USING") == 0) + else if (MATCHES4("ON", "", "USING", "") && + !MATCHES6("POLICY", "", "", "", "", "") && + !MATCHES4("FOR", "", "", "")) COMPLETE_WITH_CONST("("); /* CREATE POLICY */ /* Complete "CREATE POLICY ON" */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "POLICY") == 0) + else if (MATCHES3("CREATE", "POLICY", "")) COMPLETE_WITH_CONST("ON"); /* Complete "CREATE POLICY ON
" */ - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "POLICY") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("CREATE", "POLICY", "", "ON")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* Complete "CREATE POLICY ON
FOR|TO|USING|WITH CHECK" */ - else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && - pg_strcasecmp(prev4_wd, "POLICY") == 0 && - pg_strcasecmp(prev2_wd, "ON") == 0) - { - static const char *const list_POLICYOPTIONS[] = - {"FOR", "TO", "USING", "WITH CHECK", NULL}; - - COMPLETE_WITH_LIST(list_POLICYOPTIONS); - } + else if (MATCHES5("CREATE", "POLICY", "", "ON", "
")) + COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK"); /* * Complete "CREATE POLICY ON
FOR * ALL|SELECT|INSERT|UPDATE|DELETE" */ - else if (pg_strcasecmp(prev6_wd, "CREATE") == 0 && - pg_strcasecmp(prev5_wd, "POLICY") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "FOR") == 0) - { - static const char *const list_POLICYCMDS[] = - {"ALL", "SELECT", "INSERT", "UPDATE", "DELETE", NULL}; - - COMPLETE_WITH_LIST(list_POLICYCMDS); - } + else if (MATCHES6("CREATE", "POLICY", "", "ON", "
", "FOR")) + COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE"); /* Complete "CREATE POLICY ON
FOR INSERT TO|WITH CHECK" */ - else if (pg_strcasecmp(prev6_wd, "POLICY") == 0 && - pg_strcasecmp(prev4_wd, "ON") == 0 && - pg_strcasecmp(prev2_wd, "FOR") == 0 && - pg_strcasecmp(prev_wd, "INSERT") == 0) - { - static const char *const list_POLICYOPTIONS[] = - {"TO", "WITH CHECK", NULL}; - - COMPLETE_WITH_LIST(list_POLICYOPTIONS); - } + else if (MATCHES6("POLICY", "", "ON", "
", "FOR", "INSERT")) + COMPLETE_WITH_LIST2("TO", "WITH CHECK"); /* * Complete "CREATE POLICY ON
FOR SELECT TO|USING" Complete * "CREATE POLICY ON
FOR DELETE TO|USING" */ - else if (pg_strcasecmp(prev6_wd, "POLICY") == 0 && - pg_strcasecmp(prev4_wd, "ON") == 0 && - pg_strcasecmp(prev2_wd, "FOR") == 0 && - (pg_strcasecmp(prev_wd, "SELECT") == 0 || - pg_strcasecmp(prev_wd, "DELETE") == 0)) - { - static const char *const list_POLICYOPTIONS[] = - {"TO", "USING", NULL}; - - COMPLETE_WITH_LIST(list_POLICYOPTIONS); - } + else if (MATCHES6("POLICY", "", "ON", "
", "FOR", "SELECT|DELETE")) + COMPLETE_WITH_LIST2("TO", "USING"); /* * Complete "CREATE POLICY ON
FOR ALL TO|USING|WITH CHECK" * Complete "CREATE POLICY ON
FOR UPDATE TO|USING|WITH * CHECK" */ - else if (pg_strcasecmp(prev6_wd, "POLICY") == 0 && - pg_strcasecmp(prev4_wd, "ON") == 0 && - pg_strcasecmp(prev2_wd, "FOR") == 0 && - (pg_strcasecmp(prev_wd, "ALL") == 0 || - pg_strcasecmp(prev_wd, "UPDATE") == 0)) - { - static const char *const list_POLICYOPTIONS[] = - {"TO", "USING", "WITH CHECK", NULL}; - - COMPLETE_WITH_LIST(list_POLICYOPTIONS); - } + else if (MATCHES6("POLICY", "", "ON", "
", "FOR", "ALL|UPDATE")) + COMPLETE_WITH_LIST3("TO", "USING", "WITH CHECK"); /* Complete "CREATE POLICY ON
TO " */ - else if (pg_strcasecmp(prev6_wd, "CREATE") == 0 && - pg_strcasecmp(prev5_wd, "POLICY") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "TO") == 0) + else if (MATCHES6("CREATE", "POLICY", "", "ON", "
", "TO")) COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); /* Complete "CREATE POLICY ON
USING (" */ - else if (pg_strcasecmp(prev6_wd, "CREATE") == 0 && - pg_strcasecmp(prev5_wd, "POLICY") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "USING") == 0) + else if (MATCHES6("CREATE", "POLICY", "", "ON", "
", "USING")) COMPLETE_WITH_CONST("("); /* CREATE RULE */ /* Complete "CREATE RULE " with "AS" */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "RULE") == 0) + else if (MATCHES3("CREATE", "RULE", "")) COMPLETE_WITH_CONST("AS"); /* Complete "CREATE RULE AS with "ON" */ - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "RULE") == 0 && - pg_strcasecmp(prev_wd, "AS") == 0) + else if (MATCHES4("CREATE", "RULE", "", "AS")) COMPLETE_WITH_CONST("ON"); /* Complete "RULE * AS ON" with SELECT|UPDATE|DELETE|INSERT */ - else if (pg_strcasecmp(prev4_wd, "RULE") == 0 && - pg_strcasecmp(prev2_wd, "AS") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) - { - static const char *const rule_events[] = - {"SELECT", "UPDATE", "INSERT", "DELETE", NULL}; - - COMPLETE_WITH_LIST(rule_events); - } + else if (MATCHES4("RULE", "", "AS", "ON")) + COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE"); /* Complete "AS ON " with a "TO" */ - else if (pg_strcasecmp(prev3_wd, "AS") == 0 && - pg_strcasecmp(prev2_wd, "ON") == 0 && - (pg_toupper((unsigned char) prev_wd[4]) == 'T' || - pg_toupper((unsigned char) prev_wd[5]) == 'T')) + else if (MATCHES3("AS", "ON", "SELECT|UPDATE|DELETE|INSERT")) COMPLETE_WITH_CONST("TO"); /* Complete "AS ON TO" with a table name */ - else if (pg_strcasecmp(prev4_wd, "AS") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "TO") == 0) + else if (MATCHES4("AS", "ON", "SELECT|UPDATE|DELETE|INSERT", "TO")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* CREATE TEMP/TEMPORARY SEQUENCE */ - else if ((pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "SEQUENCE") == 0) || - (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - (pg_strcasecmp(prev3_wd, "TEMP") == 0 || - pg_strcasecmp(prev3_wd, "TEMPORARY") == 0) && - pg_strcasecmp(prev2_wd, "SEQUENCE") == 0)) - { - static const char *const list_CREATESEQUENCE[] = - {"INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE", - "CYCLE", "OWNED BY", "START WITH", NULL}; - - COMPLETE_WITH_LIST(list_CREATESEQUENCE); - } + else if (MATCHES3("CREATE", "SEQUENCE", "") || + MATCHES4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", "")) + COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE", + "CYCLE", "OWNED BY", "START WITH"); /* CREATE TEMP/TEMPORARY SEQUENCE NO */ - else if (((pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "SEQUENCE") == 0) || - (pg_strcasecmp(prev5_wd, "CREATE") == 0 && - (pg_strcasecmp(prev4_wd, "TEMP") == 0 || - pg_strcasecmp(prev4_wd, "TEMPORARY") == 0) && - pg_strcasecmp(prev3_wd, "SEQUENCE") == 0)) && - pg_strcasecmp(prev_wd, "NO") == 0) - { - static const char *const list_CREATESEQUENCE2[] = - {"MINVALUE", "MAXVALUE", "CYCLE", NULL}; - - COMPLETE_WITH_LIST(list_CREATESEQUENCE2); - } + else if (MATCHES4("CREATE", "SEQUENCE", "", "NO") || + MATCHES5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", "", "NO")) + COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE"); /* CREATE SERVER */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "SERVER") == 0) - { - static const char *const list_CREATE_SERVER[] = - {"TYPE", "VERSION", "FOREIGN DATA WRAPPER", NULL}; - - COMPLETE_WITH_LIST(list_CREATE_SERVER); - } + else if (MATCHES3("CREATE", "SERVER", "")) + COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER"); /* CREATE TABLE */ /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */ - else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && - (pg_strcasecmp(prev_wd, "TEMP") == 0 || - pg_strcasecmp(prev_wd, "TEMPORARY") == 0)) - { - static const char *const list_TEMP[] = - {"SEQUENCE", "TABLE", "VIEW", NULL}; - - COMPLETE_WITH_LIST(list_TEMP); - } + else if (MATCHES2("CREATE", "TEMP|TEMPORARY")) + COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW"); /* Complete "CREATE UNLOGGED" with TABLE */ - else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && - pg_strcasecmp(prev_wd, "UNLOGGED") == 0) - { - static const char *const list_UNLOGGED[] = - {"TABLE", "MATERIALIZED VIEW", NULL}; - - COMPLETE_WITH_LIST(list_UNLOGGED); - } + else if (MATCHES2("CREATE", "UNLOGGED")) + COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW"); /* CREATE TABLESPACE */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "TABLESPACE") == 0) - { - static const char *const list_CREATETABLESPACE[] = - {"OWNER", "LOCATION", NULL}; - - COMPLETE_WITH_LIST(list_CREATETABLESPACE); - } + else if (MATCHES3("CREATE", "TABLESPACE", "")) + COMPLETE_WITH_LIST2("OWNER", "LOCATION"); /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */ - else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && - pg_strcasecmp(prev4_wd, "TABLESPACE") == 0 && - pg_strcasecmp(prev2_wd, "OWNER") == 0) - { + else if (MATCHES5("CREATE", "TABLESPACE", "", "OWNER", "")) COMPLETE_WITH_CONST("LOCATION"); - } /* CREATE TEXT SEARCH */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "TEXT") == 0 && - pg_strcasecmp(prev_wd, "SEARCH") == 0) - { - static const char *const list_CREATETEXTSEARCH[] = - {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL}; - - COMPLETE_WITH_LIST(list_CREATETEXTSEARCH); - } - else if (pg_strcasecmp(prev4_wd, "TEXT") == 0 && - pg_strcasecmp(prev3_wd, "SEARCH") == 0 && - pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0) + else if (MATCHES3("CREATE", "TEXT", "SEARCH")) + COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE"); + else if (MATCHES4("TEXT", "SEARCH", "CONFIGURATION", "")) COMPLETE_WITH_CONST("("); /* CREATE TRIGGER */ /* complete CREATE TRIGGER with BEFORE,AFTER */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "TRIGGER") == 0) - { - static const char *const list_CREATETRIGGER[] = - {"BEFORE", "AFTER", "INSTEAD OF", NULL}; - - COMPLETE_WITH_LIST(list_CREATETRIGGER); - } + else if (MATCHES3("CREATE", "TRIGGER", "")) + COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF"); /* complete CREATE TRIGGER BEFORE,AFTER with an event */ - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && - (pg_strcasecmp(prev_wd, "BEFORE") == 0 || - pg_strcasecmp(prev_wd, "AFTER") == 0)) - { - static const char *const list_CREATETRIGGER_EVENTS[] = - {"INSERT", "DELETE", "UPDATE", "TRUNCATE", NULL}; - - COMPLETE_WITH_LIST(list_CREATETRIGGER_EVENTS); - } + else if (MATCHES4("CREATE", "TRIGGER", "", "BEFORE|AFTER")) + COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE"); /* complete CREATE TRIGGER INSTEAD OF with an event */ - else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && - pg_strcasecmp(prev4_wd, "TRIGGER") == 0 && - pg_strcasecmp(prev2_wd, "INSTEAD") == 0 && - pg_strcasecmp(prev_wd, "OF") == 0) - { - static const char *const list_CREATETRIGGER_EVENTS[] = - {"INSERT", "DELETE", "UPDATE", NULL}; - - COMPLETE_WITH_LIST(list_CREATETRIGGER_EVENTS); - } + else if (MATCHES5("CREATE", "TRIGGER", "", "INSTEAD", "OF")) + COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE"); /* complete CREATE TRIGGER BEFORE,AFTER sth with OR,ON */ - else if ((pg_strcasecmp(prev5_wd, "CREATE") == 0 && - pg_strcasecmp(prev4_wd, "TRIGGER") == 0 && - (pg_strcasecmp(prev2_wd, "BEFORE") == 0 || - pg_strcasecmp(prev2_wd, "AFTER") == 0)) || - (pg_strcasecmp(prev5_wd, "TRIGGER") == 0 && - pg_strcasecmp(prev3_wd, "INSTEAD") == 0 && - pg_strcasecmp(prev2_wd, "OF") == 0)) - { - static const char *const list_CREATETRIGGER2[] = - {"ON", "OR", NULL}; - - COMPLETE_WITH_LIST(list_CREATETRIGGER2); - } + else if (MATCHES5("CREATE", "TRIGGER", "", "BEFORE|AFTER", "") || + MATCHES6("CREATE", "TRIGGER", "", "INSTEAD", "OF", "")) + COMPLETE_WITH_LIST2("ON", "OR"); /* * complete CREATE TRIGGER BEFORE,AFTER event ON with a list of * tables */ - else if (pg_strcasecmp(prev5_wd, "TRIGGER") == 0 && - (pg_strcasecmp(prev3_wd, "BEFORE") == 0 || - pg_strcasecmp(prev3_wd, "AFTER") == 0) && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES5("TRIGGER", "", "BEFORE|AFTER", "", "ON")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */ - else if (pg_strcasecmp(prev4_wd, "INSTEAD") == 0 && - pg_strcasecmp(prev3_wd, "OF") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("INSTEAD", "OF", "", "ON")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL); /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */ - else if (pg_strcasecmp(prev_wd, "EXECUTE") == 0 && - !(pg_strcasecmp(prev2_wd, "GRANT") == 0 && prev3_wd[0] == '\0') && - prev2_wd[0] != '\0') + else if (MATCHES1("EXECUTE") && !MATCHES3("", "|GRANT", "EXECUTE")) COMPLETE_WITH_CONST("PROCEDURE"); /* CREATE ROLE,USER,GROUP */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - !(pg_strcasecmp(prev2_wd, "USER") == 0 && pg_strcasecmp(prev_wd, "MAPPING") == 0) && - (pg_strcasecmp(prev2_wd, "ROLE") == 0 || - pg_strcasecmp(prev2_wd, "GROUP") == 0 || pg_strcasecmp(prev2_wd, "USER") == 0)) + else if (MATCHES3("CREATE", "ROLE|GROUP|USER", "") && + !MATCHES3("CREATE", "USER", "MAPPING")) { static const char *const list_CREATEROLE[] = {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE", @@ -2644,11 +2018,7 @@ psql_completion(const char *text, int start, int end) } /* CREATE ROLE,USER,GROUP WITH */ - else if ((pg_strcasecmp(prev4_wd, "CREATE") == 0 && - (pg_strcasecmp(prev3_wd, "ROLE") == 0 || - pg_strcasecmp(prev3_wd, "GROUP") == 0 || - pg_strcasecmp(prev3_wd, "USER") == 0) && - pg_strcasecmp(prev_wd, "WITH") == 0)) + else if (MATCHES4("CREATE", "ROLE|GROUP|USER", "", "WITH")) { /* Similar to the above, but don't complete "WITH" again. */ static const char *const list_CREATEROLE_WITH[] = @@ -2666,91 +2036,47 @@ psql_completion(const char *text, int start, int end) * complete CREATE ROLE,USER,GROUP ENCRYPTED,UNENCRYPTED with * PASSWORD */ - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - (pg_strcasecmp(prev3_wd, "ROLE") == 0 || - pg_strcasecmp(prev3_wd, "GROUP") == 0 || pg_strcasecmp(prev3_wd, "USER") == 0) && - (pg_strcasecmp(prev_wd, "ENCRYPTED") == 0 || pg_strcasecmp(prev_wd, "UNENCRYPTED") == 0)) - { + else if (MATCHES4("CREATE", "ROLE|USER|GROUP", "", "ENCRYPTED|UNENCRYPTED")) COMPLETE_WITH_CONST("PASSWORD"); - } /* complete CREATE ROLE,USER,GROUP IN with ROLE,GROUP */ - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - (pg_strcasecmp(prev3_wd, "ROLE") == 0 || - pg_strcasecmp(prev3_wd, "GROUP") == 0 || pg_strcasecmp(prev3_wd, "USER") == 0) && - pg_strcasecmp(prev_wd, "IN") == 0) - { - static const char *const list_CREATEROLE3[] = - {"GROUP", "ROLE", NULL}; - - COMPLETE_WITH_LIST(list_CREATEROLE3); - } + else if (MATCHES4("CREATE", "ROLE|USER|GROUP", "", "IN")) + COMPLETE_WITH_LIST2("GROUP", "ROLE"); /* CREATE VIEW */ /* Complete CREATE VIEW with AS */ - else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && - pg_strcasecmp(prev2_wd, "VIEW") == 0) + else if (MATCHES3("CREATE", "VIEW", "")) COMPLETE_WITH_CONST("AS"); /* Complete "CREATE VIEW AS with "SELECT" */ - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "VIEW") == 0 && - pg_strcasecmp(prev_wd, "AS") == 0) + else if (MATCHES4("CREATE", "VIEW", "", "AS")) COMPLETE_WITH_CONST("SELECT"); /* CREATE MATERIALIZED VIEW */ - else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && - pg_strcasecmp(prev_wd, "MATERIALIZED") == 0) + else if (MATCHES2("CREATE", "MATERIALIZED")) COMPLETE_WITH_CONST("VIEW"); /* Complete CREATE MATERIALIZED VIEW with AS */ - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev2_wd, "VIEW") == 0) + else if (MATCHES3("CREATE", "MATERIALIZED", "VIEW")) COMPLETE_WITH_CONST("AS"); /* Complete "CREATE MATERIALIZED VIEW AS with "SELECT" */ - else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && - pg_strcasecmp(prev4_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev3_wd, "VIEW") == 0 && - pg_strcasecmp(prev_wd, "AS") == 0) + else if (MATCHES5("CREATE", "MATERIALIZED", "VIEW", "", "AS")) COMPLETE_WITH_CONST("SELECT"); /* CREATE EVENT TRIGGER */ - else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && - pg_strcasecmp(prev_wd, "EVENT") == 0) + else if (MATCHES2("CREATE", "EVENT")) COMPLETE_WITH_CONST("TRIGGER"); /* Complete CREATE EVENT TRIGGER with ON */ - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "EVENT") == 0 && - pg_strcasecmp(prev2_wd, "TRIGGER") == 0) + else if (MATCHES4("CREATE", "EVENT", "TRIGGER", "")) COMPLETE_WITH_CONST("ON"); /* Complete CREATE EVENT TRIGGER ON with event_type */ - else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && - pg_strcasecmp(prev4_wd, "EVENT") == 0 && - pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) - { - static const char *const list_CREATE_EVENT_TRIGGER_ON[] = - {"ddl_command_start", "ddl_command_end", "sql_drop", NULL}; - - COMPLETE_WITH_LIST(list_CREATE_EVENT_TRIGGER_ON); - } + else if (MATCHES5("CREATE", "EVENT", "TRIGGER", "", "ON")) + COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop"); /* DECLARE */ - else if (pg_strcasecmp(prev2_wd, "DECLARE") == 0) - { - static const char *const list_DECLARE[] = - {"BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR", NULL}; - - COMPLETE_WITH_LIST(list_DECLARE); - } + else if (MATCHES2("DECLARE", "")) + COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR"); /* CURSOR */ - else if (pg_strcasecmp(prev_wd, "CURSOR") == 0) - { - static const char *const list_DECLARECURSOR[] = - {"WITH HOLD", "WITHOUT HOLD", "FOR", NULL}; - - COMPLETE_WITH_LIST(list_DECLARECURSOR); - } - + else if (MATCHES1("CURSOR")) + COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR"); /* DELETE */ @@ -2758,231 +2084,109 @@ psql_completion(const char *text, int start, int end) * Complete DELETE with FROM (only if the word before that is not "ON" * (cf. rules) or "BEFORE" or "AFTER" (cf. triggers) or GRANT) */ - else if (pg_strcasecmp(prev_wd, "DELETE") == 0 && - !(pg_strcasecmp(prev2_wd, "ON") == 0 || - pg_strcasecmp(prev2_wd, "GRANT") == 0 || - pg_strcasecmp(prev2_wd, "BEFORE") == 0 || - pg_strcasecmp(prev2_wd, "AFTER") == 0)) + else if (MATCHES1("DELETE") && !MATCHES2("ON|GRANT|BEFORE|AFTER", "DELETE")) COMPLETE_WITH_CONST("FROM"); /* Complete DELETE FROM with a list of tables */ - else if (pg_strcasecmp(prev2_wd, "DELETE") == 0 && - pg_strcasecmp(prev_wd, "FROM") == 0) + else if (MATCHES2("DELETE", "FROM")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); /* Complete DELETE FROM
*/ - else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 && - pg_strcasecmp(prev2_wd, "FROM") == 0) - { - static const char *const list_DELETE[] = - {"USING", "WHERE", "SET", NULL}; - - COMPLETE_WITH_LIST(list_DELETE); - } + else if (MATCHES3("DELETE", "FROM", "
")) + COMPLETE_WITH_LIST3("USING", "WHERE", "SET"); /* XXX: implement tab completion for DELETE ... USING */ /* DISCARD */ - else if (pg_strcasecmp(prev_wd, "DISCARD") == 0) - { - static const char *const list_DISCARD[] = - {"ALL", "PLANS", "SEQUENCES", "TEMP", NULL}; - - COMPLETE_WITH_LIST(list_DISCARD); - } + else if (MATCHES1("DISCARD")) + COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP"); /* DO */ /* * Complete DO with LANGUAGE. */ - else if (pg_strcasecmp(prev_wd, "DO") == 0) - { - static const char *const list_DO[] = - {"LANGUAGE", NULL}; - - COMPLETE_WITH_LIST(list_DO); - } + else if (MATCHES1("DO")) + COMPLETE_WITH_CONST("LANGUAGE"); /* DROP (when not the previous word) */ /* DROP AGGREGATE */ - else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "AGGREGATE") == 0) + else if (MATCHES3("DROP", "AGGREGATE", "")) COMPLETE_WITH_CONST("("); /* DROP object with CASCADE / RESTRICT */ - else if ((pg_strcasecmp(prev3_wd, "DROP") == 0 && - (pg_strcasecmp(prev2_wd, "COLLATION") == 0 || - pg_strcasecmp(prev2_wd, "CONVERSION") == 0 || - pg_strcasecmp(prev2_wd, "DOMAIN") == 0 || - pg_strcasecmp(prev2_wd, "EXTENSION") == 0 || - pg_strcasecmp(prev2_wd, "FUNCTION") == 0 || - pg_strcasecmp(prev2_wd, "INDEX") == 0 || - pg_strcasecmp(prev2_wd, "LANGUAGE") == 0 || - pg_strcasecmp(prev2_wd, "SCHEMA") == 0 || - pg_strcasecmp(prev2_wd, "SEQUENCE") == 0 || - pg_strcasecmp(prev2_wd, "SERVER") == 0 || - pg_strcasecmp(prev2_wd, "TABLE") == 0 || - pg_strcasecmp(prev2_wd, "TYPE") == 0 || - pg_strcasecmp(prev2_wd, "VIEW") == 0)) || - (pg_strcasecmp(prev4_wd, "DROP") == 0 && - pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 && - prev_wd[strlen(prev_wd) - 1] == ')') || - (pg_strcasecmp(prev4_wd, "DROP") == 0 && - pg_strcasecmp(prev3_wd, "EVENT") == 0 && - pg_strcasecmp(prev2_wd, "TRIGGER") == 0) || - (pg_strcasecmp(prev5_wd, "DROP") == 0 && - pg_strcasecmp(prev4_wd, "FOREIGN") == 0 && - pg_strcasecmp(prev3_wd, "DATA") == 0 && - pg_strcasecmp(prev2_wd, "WRAPPER") == 0) || - (pg_strcasecmp(prev5_wd, "DROP") == 0 && - pg_strcasecmp(prev4_wd, "TEXT") == 0 && - pg_strcasecmp(prev3_wd, "SEARCH") == 0 && - (pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0 || - pg_strcasecmp(prev2_wd, "DICTIONARY") == 0 || - pg_strcasecmp(prev2_wd, "PARSER") == 0 || - pg_strcasecmp(prev2_wd, "TEMPLATE") == 0)) - ) - { - if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "FUNCTION") == 0) - { + else if (MATCHES3("DROP", + "COLLATION|CONVERSION|DOMAIN|EXTENSION|FUNCTION|INDEX|LANGUAGE|SCHEMA|SEQUENCES|SERVER|TABLE|TYPE|VIEW", + "") || + (MATCHES4("DROP", "AGGREGATE", "", "") && ends_with(prev_wd, ')')) || + MATCHES4("DROP", "EVENT", "TRIGGER", "") || + MATCHES5("DROP", "FOREIGN", "DATA", "WRAPPER", "") || + MATCHES5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", "")) + { + if (MATCHES3("DROP", "FUNCTION", "")) COMPLETE_WITH_CONST("("); - } else - { - static const char *const list_DROPCR[] = - {"CASCADE", "RESTRICT", NULL}; - - COMPLETE_WITH_LIST(list_DROPCR); - } - } - else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && - pg_strcasecmp(prev_wd, "FOREIGN") == 0) - { - static const char *const drop_CREATE_FOREIGN[] = - {"DATA WRAPPER", "TABLE", NULL}; - - COMPLETE_WITH_LIST(drop_CREATE_FOREIGN); + COMPLETE_WITH_LIST2("CASCADE", "RESTRICT"); } + else if (MATCHES2("DROP", "FOREIGN")) + COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE"); /* DROP MATERIALIZED VIEW */ - else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && - pg_strcasecmp(prev_wd, "MATERIALIZED") == 0) - { + else if (MATCHES2("DROP", "MATERIALIZED")) COMPLETE_WITH_CONST("VIEW"); - } - else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev_wd, "VIEW") == 0) - { + else if (MATCHES3("DROP", "MATERIALIZED", "VIEW")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); - } - else if (pg_strcasecmp(prev4_wd, "DROP") == 0 && - (pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 || - pg_strcasecmp(prev3_wd, "FUNCTION") == 0) && - pg_strcasecmp(prev_wd, "(") == 0) + else if (MATCHES4("DROP", "AGGREGATE|FUNCTION", "", "(")) COMPLETE_WITH_FUNCTION_ARG(prev2_wd); /* DROP OWNED BY */ - else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && - pg_strcasecmp(prev_wd, "OWNED") == 0) + else if (MATCHES2("DROP", "OWNED")) COMPLETE_WITH_CONST("BY"); - else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "OWNED") == 0 && - pg_strcasecmp(prev_wd, "BY") == 0) + else if (MATCHES3("DROP", "OWNED", "BY")) COMPLETE_WITH_QUERY(Query_for_list_of_roles); - else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "TEXT") == 0 && - pg_strcasecmp(prev_wd, "SEARCH") == 0) - { - - static const char *const list_ALTERTEXTSEARCH[] = - {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL}; - - COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH); - } + else if (MATCHES3("DROP", "TEXT", "SEARCH")) + COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE"); /* DROP TRIGGER */ - else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "TRIGGER") == 0) - { + else if (MATCHES3("DROP", "TRIGGER", "")) COMPLETE_WITH_CONST("ON"); - } - else if (pg_strcasecmp(prev4_wd, "DROP") == 0 && - pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("DROP", "TRIGGER", "", "ON")) { completion_info_charp = prev2_wd; COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger); } - else if (pg_strcasecmp(prev5_wd, "DROP") == 0 && - pg_strcasecmp(prev4_wd, "TRIGGER") == 0 && - pg_strcasecmp(prev2_wd, "ON") == 0) - { - static const char *const list_DROPCR[] = - {"CASCADE", "RESTRICT", NULL}; - - COMPLETE_WITH_LIST(list_DROPCR); - } + else if (MATCHES5("DROP", "TRIGGER", "", "ON", "")) + COMPLETE_WITH_LIST2("CASCADE", "RESTRICT"); /* DROP EVENT TRIGGER */ - else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && - pg_strcasecmp(prev_wd, "EVENT") == 0) - { + else if (MATCHES2("DROP", "EVENT")) COMPLETE_WITH_CONST("TRIGGER"); - } - else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "EVENT") == 0 && - pg_strcasecmp(prev_wd, "TRIGGER") == 0) - { + else if (MATCHES3("DROP", "EVENT", "TRIGGER")) COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers); - } /* DROP POLICY */ - else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && - pg_strcasecmp(prev_wd, "POLICY") == 0) - { + else if (MATCHES2("DROP", "POLICY")) COMPLETE_WITH_QUERY(Query_for_list_of_policies); - } /* DROP POLICY ON */ - else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "POLICY") == 0) - { + else if (MATCHES3("DROP", "POLICY", "")) COMPLETE_WITH_CONST("ON"); - } /* DROP POLICY ON
*/ - else if (pg_strcasecmp(prev4_wd, "DROP") == 0 && - pg_strcasecmp(prev3_wd, "POLICY") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("DROP", "POLICY", "", "ON")) { completion_info_charp = prev2_wd; COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy); } /* DROP RULE */ - else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && - pg_strcasecmp(prev2_wd, "RULE") == 0) - { + else if (MATCHES3("DROP", "RULE", "")) COMPLETE_WITH_CONST("ON"); - } - else if (pg_strcasecmp(prev4_wd, "DROP") == 0 && - pg_strcasecmp(prev3_wd, "RULE") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES4("DROP", "RULE", "", "ON")) { completion_info_charp = prev2_wd; COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule); } - else if (pg_strcasecmp(prev5_wd, "DROP") == 0 && - pg_strcasecmp(prev4_wd, "RULE") == 0 && - pg_strcasecmp(prev2_wd, "ON") == 0) - { - static const char *const list_DROPCR[] = - {"CASCADE", "RESTRICT", NULL}; - - COMPLETE_WITH_LIST(list_DROPCR); - } + else if (MATCHES5("DROP", "RULE", "", "ON", "")) + COMPLETE_WITH_LIST2("CASCADE", "RESTRICT"); /* EXECUTE, but not EXECUTE embedded in other commands */ - else if (pg_strcasecmp(prev_wd, "EXECUTE") == 0 && - prev2_wd[0] == '\0') + else if (MATCHES2("", "EXECUTE")) COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements); /* EXPLAIN */ @@ -2990,85 +2194,45 @@ psql_completion(const char *text, int start, int end) /* * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands */ - else if (pg_strcasecmp(prev_wd, "EXPLAIN") == 0) - { - static const char *const list_EXPLAIN[] = - {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "ANALYZE", "VERBOSE", NULL}; - - COMPLETE_WITH_LIST(list_EXPLAIN); - } - else if (pg_strcasecmp(prev2_wd, "EXPLAIN") == 0 && - pg_strcasecmp(prev_wd, "ANALYZE") == 0) - { - static const char *const list_EXPLAIN[] = - {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "VERBOSE", NULL}; - - COMPLETE_WITH_LIST(list_EXPLAIN); - } - else if ((pg_strcasecmp(prev2_wd, "EXPLAIN") == 0 && - pg_strcasecmp(prev_wd, "VERBOSE") == 0) || - (pg_strcasecmp(prev3_wd, "EXPLAIN") == 0 && - pg_strcasecmp(prev2_wd, "ANALYZE") == 0 && - pg_strcasecmp(prev_wd, "VERBOSE") == 0)) - { - static const char *const list_EXPLAIN[] = - {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", NULL}; - - COMPLETE_WITH_LIST(list_EXPLAIN); - } + else if (MATCHES1("EXPLAIN")) + COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", + "ANALYZE", "VERBOSE"); + else if (MATCHES2("EXPLAIN", "ANALYZE|ANALYSE")) + COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "VERBOSE"); + else if (MATCHES2("EXPLAIN", "VERBOSE") || + MATCHES3("EXPLAIN", "ANALYZE|ANALYSE", "VERBOSE")) + COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE"); /* FETCH && MOVE */ /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */ - else if (pg_strcasecmp(prev_wd, "FETCH") == 0 || - pg_strcasecmp(prev_wd, "MOVE") == 0) - { - static const char *const list_FETCH1[] = - {"ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE", NULL}; - - COMPLETE_WITH_LIST(list_FETCH1); - } + else if (MATCHES1("FETCH|MOVE")) + COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE"); /* Complete FETCH with one of ALL, NEXT, PRIOR */ - else if (pg_strcasecmp(prev2_wd, "FETCH") == 0 || - pg_strcasecmp(prev2_wd, "MOVE") == 0) - { - static const char *const list_FETCH2[] = - {"ALL", "NEXT", "PRIOR", NULL}; - - COMPLETE_WITH_LIST(list_FETCH2); - } + else if (MATCHES2("FETCH|MOVE", "")) + COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR"); /* * Complete FETCH with "FROM" or "IN". These are equivalent, * but we may as well tab-complete both: perhaps some users prefer one * variant or the other. */ - else if (pg_strcasecmp(prev3_wd, "FETCH") == 0 || - pg_strcasecmp(prev3_wd, "MOVE") == 0) - { - static const char *const list_FROMIN[] = - {"FROM", "IN", NULL}; - - COMPLETE_WITH_LIST(list_FROMIN); - } + else if (MATCHES3("FETCH|MOVE", "", "")) + COMPLETE_WITH_LIST2("FROM", "IN"); /* FOREIGN DATA WRAPPER */ /* applies in ALTER/DROP FDW and in CREATE SERVER */ - else if (pg_strcasecmp(prev4_wd, "CREATE") != 0 && - pg_strcasecmp(prev3_wd, "FOREIGN") == 0 && - pg_strcasecmp(prev2_wd, "DATA") == 0 && - pg_strcasecmp(prev_wd, "WRAPPER") == 0) + else if (MATCHES3("FOREIGN", "DATA", "WRAPPER") && + !MATCHES4("CREATE", "FOREIGN", "DATA", "WRAPPER")) COMPLETE_WITH_QUERY(Query_for_list_of_fdws); /* FOREIGN TABLE */ - else if (pg_strcasecmp(prev3_wd, "CREATE") != 0 && - pg_strcasecmp(prev2_wd, "FOREIGN") == 0 && - pg_strcasecmp(prev_wd, "TABLE") == 0) + else if (MATCHES2("FOREIGN", "TABLE") && + !MATCHES3("CREATE", "FOREIGN", "TABLE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL); /* GRANT && REVOKE */ /* Complete GRANT/REVOKE with a list of roles and privileges */ - else if (pg_strcasecmp(prev_wd, "GRANT") == 0 || - pg_strcasecmp(prev_wd, "REVOKE") == 0) + else if (MATCHES1("GRANT|REVOKE")) { COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'SELECT'" @@ -3090,27 +2254,13 @@ psql_completion(const char *text, int start, int end) * Complete GRANT/REVOKE with "ON", GRANT/REVOKE with * TO/FROM */ - else if (pg_strcasecmp(prev2_wd, "GRANT") == 0 || - pg_strcasecmp(prev2_wd, "REVOKE") == 0) + else if (MATCHES2("GRANT|REVOKE", "")) { - if (pg_strcasecmp(prev_wd, "SELECT") == 0 - || pg_strcasecmp(prev_wd, "INSERT") == 0 - || pg_strcasecmp(prev_wd, "UPDATE") == 0 - || pg_strcasecmp(prev_wd, "DELETE") == 0 - || pg_strcasecmp(prev_wd, "TRUNCATE") == 0 - || pg_strcasecmp(prev_wd, "REFERENCES") == 0 - || pg_strcasecmp(prev_wd, "TRIGGER") == 0 - || pg_strcasecmp(prev_wd, "CREATE") == 0 - || pg_strcasecmp(prev_wd, "CONNECT") == 0 - || pg_strcasecmp(prev_wd, "TEMPORARY") == 0 - || pg_strcasecmp(prev_wd, "TEMP") == 0 - || pg_strcasecmp(prev_wd, "EXECUTE") == 0 - || pg_strcasecmp(prev_wd, "USAGE") == 0 - || pg_strcasecmp(prev_wd, "ALL") == 0) + if (MATCHES1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL")) COMPLETE_WITH_CONST("ON"); else { - if (pg_strcasecmp(prev2_wd, "GRANT") == 0) + if (MATCHES2("GRANT", "")) COMPLETE_WITH_CONST("TO"); else COMPLETE_WITH_CONST("FROM"); @@ -3128,9 +2278,7 @@ psql_completion(const char *text, int start, int end) * here will only work if the privilege list contains exactly one * privilege */ - else if ((pg_strcasecmp(prev3_wd, "GRANT") == 0 || - pg_strcasecmp(prev3_wd, "REVOKE") == 0) && - pg_strcasecmp(prev_wd, "ON") == 0) + else if (MATCHES3("GRANT|REVOKE", "", "ON")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, " UNION SELECT 'DATABASE'" " UNION SELECT 'DOMAIN'" @@ -3142,195 +2290,138 @@ psql_completion(const char *text, int start, int end) " UNION SELECT 'SCHEMA'" " UNION SELECT 'TABLESPACE'" " UNION SELECT 'TYPE'"); - else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 || - pg_strcasecmp(prev4_wd, "REVOKE") == 0) && - pg_strcasecmp(prev2_wd, "ON") == 0 && - pg_strcasecmp(prev_wd, "FOREIGN") == 0) - { - static const char *const list_privilege_foreign[] = - {"DATA WRAPPER", "SERVER", NULL}; - - COMPLETE_WITH_LIST(list_privilege_foreign); - } + else if (MATCHES4("GRANT|REVOKE", "", "ON", "FOREIGN")) + COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER"); /* Complete "GRANT/REVOKE * ON * " with "TO/FROM" */ - else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 || - pg_strcasecmp(prev4_wd, "REVOKE") == 0) && - pg_strcasecmp(prev2_wd, "ON") == 0) + else if (MATCHES4("GRANT|REVOKE", "", "ON", "")) { - if (pg_strcasecmp(prev_wd, "DATABASE") == 0) + if (MATCHES1("DATABASE")) COMPLETE_WITH_QUERY(Query_for_list_of_databases); - else if (pg_strcasecmp(prev_wd, "DOMAIN") == 0) + else if (MATCHES1("DOMAIN")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL); - else if (pg_strcasecmp(prev_wd, "FUNCTION") == 0) + else if (MATCHES1("FUNCTION")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL); - else if (pg_strcasecmp(prev_wd, "LANGUAGE") == 0) + else if (MATCHES1("LANGUAGE")) COMPLETE_WITH_QUERY(Query_for_list_of_languages); - else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0) + else if (MATCHES1("SCHEMA")) COMPLETE_WITH_QUERY(Query_for_list_of_schemas); - else if (pg_strcasecmp(prev_wd, "TABLESPACE") == 0) + else if (MATCHES1("TABLESPACE")) COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); - else if (pg_strcasecmp(prev_wd, "TYPE") == 0) + else if (MATCHES1("TYPE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL); - else if (pg_strcasecmp(prev4_wd, "GRANT") == 0) + else if (MATCHES4("GRANT", "", "", "")) COMPLETE_WITH_CONST("TO"); else COMPLETE_WITH_CONST("FROM"); } /* Complete "GRANT/REVOKE * ON * TO/FROM" with username, GROUP, or PUBLIC */ - else if (pg_strcasecmp(prev5_wd, "GRANT") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0) + else if (MATCHES5("GRANT", "", "ON", "", "")) { - if (pg_strcasecmp(prev_wd, "TO") == 0) + if (MATCHES1("TO")) COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); else COMPLETE_WITH_CONST("TO"); } - else if (pg_strcasecmp(prev5_wd, "REVOKE") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0) + else if (MATCHES5("REVOKE", "", "ON", "", "")) { - if (pg_strcasecmp(prev_wd, "FROM") == 0) + if (MATCHES1("FROM")) COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); else COMPLETE_WITH_CONST("FROM"); } /* Complete "GRANT/REVOKE * TO/FROM" with username, GROUP, or PUBLIC */ - else if (pg_strcasecmp(prev3_wd, "GRANT") == 0 && - pg_strcasecmp(prev_wd, "TO") == 0) - { + else if (MATCHES3("GRANT", "", "TO")) COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); - } - else if (pg_strcasecmp(prev3_wd, "REVOKE") == 0 && - pg_strcasecmp(prev_wd, "FROM") == 0) - { + else if (MATCHES3("REVOKE", "", "FROM")) COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); - } /* GROUP BY */ - else if (pg_strcasecmp(prev3_wd, "FROM") == 0 && - pg_strcasecmp(prev_wd, "GROUP") == 0) + else if (MATCHES3("FROM", "", "GROUP")) COMPLETE_WITH_CONST("BY"); /* IMPORT FOREIGN SCHEMA */ - else if (pg_strcasecmp(prev_wd, "IMPORT") == 0) + else if (MATCHES1("IMPORT")) COMPLETE_WITH_CONST("FOREIGN SCHEMA"); - else if (pg_strcasecmp(prev2_wd, "IMPORT") == 0 && - pg_strcasecmp(prev_wd, "FOREIGN") == 0) + else if (MATCHES2("IMPORT", "FOREIGN")) COMPLETE_WITH_CONST("SCHEMA"); /* INSERT */ /* Complete INSERT with "INTO" */ - else if (pg_strcasecmp(prev_wd, "INSERT") == 0) + else if (MATCHES1("INSERT")) COMPLETE_WITH_CONST("INTO"); /* Complete INSERT INTO with table names */ - else if (pg_strcasecmp(prev2_wd, "INSERT") == 0 && - pg_strcasecmp(prev_wd, "INTO") == 0) + else if (MATCHES2("INSERT", "INTO")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); /* Complete "INSERT INTO
(" with attribute names */ - else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 && - pg_strcasecmp(prev3_wd, "INTO") == 0 && - pg_strcasecmp(prev_wd, "(") == 0) + else if (MATCHES4("INSERT", "INTO", "
", "(")) COMPLETE_WITH_ATTR(prev2_wd, ""); /* * Complete INSERT INTO
with "(" or "VALUES" or "SELECT" or * "TABLE" or "DEFAULT VALUES" */ - else if (pg_strcasecmp(prev3_wd, "INSERT") == 0 && - pg_strcasecmp(prev2_wd, "INTO") == 0) - { - static const char *const list_INSERT[] = - {"(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", NULL}; - - COMPLETE_WITH_LIST(list_INSERT); - } + else if (MATCHES3("INSERT", "INTO", "
")) + COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES"); /* * Complete INSERT INTO
(attribs) with "VALUES" or "SELECT" or * "TABLE" */ - else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 && - pg_strcasecmp(prev3_wd, "INTO") == 0 && - prev_wd[strlen(prev_wd) - 1] == ')') - { - static const char *const list_INSERT[] = - {"SELECT", "TABLE", "VALUES", NULL}; - - COMPLETE_WITH_LIST(list_INSERT); - } + else if (MATCHES4("INSERT", "INTO", "
", "") && ends_with(prev_wd, ')')) + COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES"); /* Insert an open parenthesis after "VALUES" */ - else if (pg_strcasecmp(prev_wd, "VALUES") == 0 && - pg_strcasecmp(prev2_wd, "DEFAULT") != 0) + else if (MATCHES1("VALUES") && !MATCHES2("DEFAULT", "VALUES")) COMPLETE_WITH_CONST("("); /* LOCK */ /* Complete LOCK [TABLE] with a list of tables */ - else if (pg_strcasecmp(prev_wd, "LOCK") == 0) + else if (MATCHES1("LOCK")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, " UNION SELECT 'TABLE'"); - else if (pg_strcasecmp(prev_wd, "TABLE") == 0 && - pg_strcasecmp(prev2_wd, "LOCK") == 0) + else if (MATCHES2("LOCK", "TABLE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, ""); /* For the following, handle the case of a single table only for now */ /* Complete LOCK [TABLE]
with "IN" */ - else if ((pg_strcasecmp(prev2_wd, "LOCK") == 0 && - pg_strcasecmp(prev_wd, "TABLE") != 0) || - (pg_strcasecmp(prev2_wd, "TABLE") == 0 && - pg_strcasecmp(prev3_wd, "LOCK") == 0)) + else if ((MATCHES2("LOCK", "
") && !MATCHES2("LOCK", "TABLE")) || + MATCHES3("LOCK", "TABLE", "
")) COMPLETE_WITH_CONST("IN"); /* Complete LOCK [TABLE]
IN with a lock mode */ - else if (pg_strcasecmp(prev_wd, "IN") == 0 && - (pg_strcasecmp(prev3_wd, "LOCK") == 0 || - (pg_strcasecmp(prev3_wd, "TABLE") == 0 && - pg_strcasecmp(prev4_wd, "LOCK") == 0))) - { - static const char *const lock_modes[] = - {"ACCESS SHARE MODE", - "ROW SHARE MODE", "ROW EXCLUSIVE MODE", - "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE", - "SHARE ROW EXCLUSIVE MODE", - "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE", NULL}; - - COMPLETE_WITH_LIST(lock_modes); - } + else if (MATCHES3("LOCK", "
", "IN") || + MATCHES4("LOCK", "TABLE", "
", "IN")) + COMPLETE_WITH_LIST8("ACCESS SHARE MODE", + "ROW SHARE MODE", "ROW EXCLUSIVE MODE", + "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE", + "SHARE ROW EXCLUSIVE MODE", + "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE"); /* NOTIFY */ - else if (pg_strcasecmp(prev_wd, "NOTIFY") == 0) + else if (MATCHES1("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'"); /* OPTIONS */ - else if (pg_strcasecmp(prev_wd, "OPTIONS") == 0) + else if (MATCHES1("OPTIONS")) COMPLETE_WITH_CONST("("); /* OWNER TO - complete with available roles */ - else if (pg_strcasecmp(prev2_wd, "OWNER") == 0 && - pg_strcasecmp(prev_wd, "TO") == 0) + else if (MATCHES2("OWNER", "TO")) COMPLETE_WITH_QUERY(Query_for_list_of_roles); /* ORDER BY */ - else if (pg_strcasecmp(prev3_wd, "FROM") == 0 && - pg_strcasecmp(prev_wd, "ORDER") == 0) + else if (MATCHES3("FROM", "", "ORDER")) COMPLETE_WITH_CONST("BY"); - else if (pg_strcasecmp(prev4_wd, "FROM") == 0 && - pg_strcasecmp(prev2_wd, "ORDER") == 0 && - pg_strcasecmp(prev_wd, "BY") == 0) + else if (MATCHES4("FROM", "", "ORDER", "BY")) COMPLETE_WITH_ATTR(prev3_wd, ""); /* PREPARE xx AS */ - else if (pg_strcasecmp(prev_wd, "AS") == 0 && - pg_strcasecmp(prev3_wd, "PREPARE") == 0) - { - static const char *const list_PREPARE[] = - {"SELECT", "UPDATE", "INSERT", "DELETE", NULL}; - - COMPLETE_WITH_LIST(list_PREPARE); - } + else if (MATCHES3("PREPARE", "", "AS")) + COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE"); /* * PREPARE TRANSACTION is missing on purpose. It's intended for transaction @@ -3338,116 +2429,72 @@ psql_completion(const char *text, int start, int end) */ /* REASSIGN OWNED BY xxx TO yyy */ - else if (pg_strcasecmp(prev_wd, "REASSIGN") == 0) + else if (MATCHES1("REASSIGN")) COMPLETE_WITH_CONST("OWNED"); - else if (pg_strcasecmp(prev_wd, "OWNED") == 0 && - pg_strcasecmp(prev2_wd, "REASSIGN") == 0) + else if (MATCHES2("REASSIGN", "OWNED")) COMPLETE_WITH_CONST("BY"); - else if (pg_strcasecmp(prev_wd, "BY") == 0 && - pg_strcasecmp(prev2_wd, "OWNED") == 0 && - pg_strcasecmp(prev3_wd, "REASSIGN") == 0) + else if (MATCHES3("REASSIGN", "OWNED", "BY")) COMPLETE_WITH_QUERY(Query_for_list_of_roles); - else if (pg_strcasecmp(prev2_wd, "BY") == 0 && - pg_strcasecmp(prev3_wd, "OWNED") == 0 && - pg_strcasecmp(prev4_wd, "REASSIGN") == 0) + else if (MATCHES4("REASSIGN", "OWNED", "BY", "")) COMPLETE_WITH_CONST("TO"); - else if (pg_strcasecmp(prev_wd, "TO") == 0 && - pg_strcasecmp(prev3_wd, "BY") == 0 && - pg_strcasecmp(prev4_wd, "OWNED") == 0 && - pg_strcasecmp(prev5_wd, "REASSIGN") == 0) + else if (MATCHES5("REASSIGN", "OWNED", "BY", "", "TO")) COMPLETE_WITH_QUERY(Query_for_list_of_roles); /* REFRESH MATERIALIZED VIEW */ - else if (pg_strcasecmp(prev_wd, "REFRESH") == 0) + else if (MATCHES1("REFRESH")) COMPLETE_WITH_CONST("MATERIALIZED VIEW"); - else if (pg_strcasecmp(prev2_wd, "REFRESH") == 0 && - pg_strcasecmp(prev_wd, "MATERIALIZED") == 0) + else if (MATCHES2("REFRESH", "MATERIALIZED")) COMPLETE_WITH_CONST("VIEW"); - else if (pg_strcasecmp(prev3_wd, "REFRESH") == 0 && - pg_strcasecmp(prev2_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev_wd, "VIEW") == 0) + else if (MATCHES3("REFRESH", "MATERIALIZED", "VIEW")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, " UNION SELECT 'CONCURRENTLY'"); - else if (pg_strcasecmp(prev4_wd, "REFRESH") == 0 && - pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev2_wd, "VIEW") == 0 && - pg_strcasecmp(prev_wd, "CONCURRENTLY") == 0) + else if (MATCHES4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); - else if (pg_strcasecmp(prev4_wd, "REFRESH") == 0 && - pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev2_wd, "VIEW") == 0) + else if (MATCHES4("REFRESH", "MATERIALIZED", "VIEW", "")) COMPLETE_WITH_CONST("WITH"); - else if (pg_strcasecmp(prev5_wd, "REFRESH") == 0 && - pg_strcasecmp(prev4_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev3_wd, "VIEW") == 0 && - pg_strcasecmp(prev2_wd, "CONCURRENTLY") == 0) + else if (MATCHES5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", "")) COMPLETE_WITH_CONST("WITH DATA"); - else if (pg_strcasecmp(prev5_wd, "REFRESH") == 0 && - pg_strcasecmp(prev4_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev3_wd, "VIEW") == 0 && - pg_strcasecmp(prev_wd, "WITH") == 0) + else if (MATCHES5("REFRESH", "MATERIALIZED", "VIEW", "", "WITH")) { static const char *const list_WITH_DATA[] = {"NO DATA", "DATA", NULL}; COMPLETE_WITH_LIST(list_WITH_DATA); } - else if (pg_strcasecmp(prev6_wd, "REFRESH") == 0 && - pg_strcasecmp(prev5_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev4_wd, "VIEW") == 0 && - pg_strcasecmp(prev3_wd, "CONCURRENTLY") == 0 && - pg_strcasecmp(prev_wd, "WITH") == 0) + else if (MATCHES6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", "", "WITH")) COMPLETE_WITH_CONST("DATA"); - else if (pg_strcasecmp(prev6_wd, "REFRESH") == 0 && - pg_strcasecmp(prev5_wd, "MATERIALIZED") == 0 && - pg_strcasecmp(prev4_wd, "VIEW") == 0 && - pg_strcasecmp(prev2_wd, "WITH") == 0 && - pg_strcasecmp(prev_wd, "NO") == 0) + else if (MATCHES6("REFRESH", "MATERIALIZED", "VIEW", "", "WITH", "NO")) COMPLETE_WITH_CONST("DATA"); /* REINDEX */ - else if (pg_strcasecmp(prev_wd, "REINDEX") == 0) + else if (MATCHES1("REINDEX")) { static const char *const list_REINDEX[] = {"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL}; COMPLETE_WITH_LIST(list_REINDEX); } - else if (pg_strcasecmp(prev2_wd, "REINDEX") == 0) + else if (MATCHES2("REINDEX", "")) { - if (pg_strcasecmp(prev_wd, "TABLE") == 0) + if (MATCHES1("TABLE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL); - else if (pg_strcasecmp(prev_wd, "INDEX") == 0) + else if (MATCHES1("INDEX")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL); - else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0) + else if (MATCHES1("SCHEMA")) COMPLETE_WITH_QUERY(Query_for_list_of_schemas); - else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 || - pg_strcasecmp(prev_wd, "DATABASE") == 0) + else if (MATCHES1("SYSTEM|DATABASE")) COMPLETE_WITH_QUERY(Query_for_list_of_databases); } /* SECURITY LABEL */ - else if (pg_strcasecmp(prev_wd, "SECURITY") == 0) + else if (MATCHES1("SECURITY")) COMPLETE_WITH_CONST("LABEL"); - else if (pg_strcasecmp(prev2_wd, "SECURITY") == 0 && - pg_strcasecmp(prev_wd, "LABEL") == 0) - { - static const char *const list_SECURITY_LABEL_preposition[] = - {"ON", "FOR"}; - - COMPLETE_WITH_LIST(list_SECURITY_LABEL_preposition); - } - else if (pg_strcasecmp(prev4_wd, "SECURITY") == 0 && - pg_strcasecmp(prev3_wd, "LABEL") == 0 && - pg_strcasecmp(prev2_wd, "FOR") == 0) + else if (MATCHES2("SECURITY", "LABEL")) + COMPLETE_WITH_LIST2("ON", "FOR"); + else if (MATCHES4("SECURITY", "LABEL", "FOR", "")) COMPLETE_WITH_CONST("ON"); - else if ((pg_strcasecmp(prev3_wd, "SECURITY") == 0 && - pg_strcasecmp(prev2_wd, "LABEL") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0) || - (pg_strcasecmp(prev5_wd, "SECURITY") == 0 && - pg_strcasecmp(prev4_wd, "LABEL") == 0 && - pg_strcasecmp(prev3_wd, "FOR") == 0 && - pg_strcasecmp(prev_wd, "ON") == 0)) + else if (MATCHES3("SECURITY", "LABEL", "ON") || + MATCHES5("SECURITY", "LABEL", "FOR", "", "ON")) { static const char *const list_SECURITY_LABEL[] = {"LANGUAGE", "SCHEMA", "SEQUENCE", "TABLE", "TYPE", "VIEW", @@ -3456,9 +2503,7 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_SECURITY_LABEL); } - else if (pg_strcasecmp(prev5_wd, "SECURITY") == 0 && - pg_strcasecmp(prev4_wd, "LABEL") == 0 && - pg_strcasecmp(prev3_wd, "ON") == 0) + else if (MATCHES5("SECURITY", "LABEL", "ON", "", "")) COMPLETE_WITH_CONST("IS"); /* SELECT */ @@ -3466,135 +2511,51 @@ psql_completion(const char *text, int start, int end) /* SET, RESET, SHOW */ /* Complete with a variable name */ - else if ((pg_strcasecmp(prev_wd, "SET") == 0 && - pg_strcasecmp(prev3_wd, "UPDATE") != 0) || - pg_strcasecmp(prev_wd, "RESET") == 0) + else if (MATCHES2("", "SET|RESET")) COMPLETE_WITH_QUERY(Query_for_list_of_set_vars); - else if (pg_strcasecmp(prev_wd, "SHOW") == 0) + else if (MATCHES1("SHOW")) COMPLETE_WITH_QUERY(Query_for_list_of_show_vars); /* Complete "SET TRANSACTION" */ - else if ((pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev_wd, "TRANSACTION") == 0) - || (pg_strcasecmp(prev2_wd, "START") == 0 - && pg_strcasecmp(prev_wd, "TRANSACTION") == 0) - || (pg_strcasecmp(prev2_wd, "BEGIN") == 0 - && pg_strcasecmp(prev_wd, "WORK") == 0) - || (pg_strcasecmp(prev2_wd, "BEGIN") == 0 - && pg_strcasecmp(prev_wd, "TRANSACTION") == 0) - || (pg_strcasecmp(prev4_wd, "SESSION") == 0 - && pg_strcasecmp(prev3_wd, "CHARACTERISTICS") == 0 - && pg_strcasecmp(prev2_wd, "AS") == 0 - && pg_strcasecmp(prev_wd, "TRANSACTION") == 0)) - { - static const char *const my_list[] = - {"ISOLATION LEVEL", "READ", NULL}; - - COMPLETE_WITH_LIST(my_list); - } - else if ((pg_strcasecmp(prev3_wd, "SET") == 0 - || pg_strcasecmp(prev3_wd, "BEGIN") == 0 - || pg_strcasecmp(prev3_wd, "START") == 0 - || (pg_strcasecmp(prev4_wd, "CHARACTERISTICS") == 0 - && pg_strcasecmp(prev3_wd, "AS") == 0)) - && (pg_strcasecmp(prev2_wd, "TRANSACTION") == 0 - || pg_strcasecmp(prev2_wd, "WORK") == 0) - && pg_strcasecmp(prev_wd, "ISOLATION") == 0) + else if (MATCHES2("SET|BEGIN|START", "TRANSACTION") || + MATCHES2("BEGIN", "WORK") || + MATCHES4("SESSION", "CHARACTERISTICS", "AS", "TRANSACTION")) + COMPLETE_WITH_LIST2("ISOLATION LEVEL", "READ"); + else if (MATCHES3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") || + MATCHES4("CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION")) COMPLETE_WITH_CONST("LEVEL"); - else if ((pg_strcasecmp(prev4_wd, "SET") == 0 - || pg_strcasecmp(prev4_wd, "BEGIN") == 0 - || pg_strcasecmp(prev4_wd, "START") == 0 - || pg_strcasecmp(prev4_wd, "AS") == 0) - && (pg_strcasecmp(prev3_wd, "TRANSACTION") == 0 - || pg_strcasecmp(prev3_wd, "WORK") == 0) - && pg_strcasecmp(prev2_wd, "ISOLATION") == 0 - && pg_strcasecmp(prev_wd, "LEVEL") == 0) - { - static const char *const my_list[] = - {"READ", "REPEATABLE", "SERIALIZABLE", NULL}; - - COMPLETE_WITH_LIST(my_list); - } - else if ((pg_strcasecmp(prev4_wd, "TRANSACTION") == 0 || - pg_strcasecmp(prev4_wd, "WORK") == 0) && - pg_strcasecmp(prev3_wd, "ISOLATION") == 0 && - pg_strcasecmp(prev2_wd, "LEVEL") == 0 && - pg_strcasecmp(prev_wd, "READ") == 0) - { - static const char *const my_list[] = - {"UNCOMMITTED", "COMMITTED", NULL}; - - COMPLETE_WITH_LIST(my_list); - } - else if ((pg_strcasecmp(prev4_wd, "TRANSACTION") == 0 || - pg_strcasecmp(prev4_wd, "WORK") == 0) && - pg_strcasecmp(prev3_wd, "ISOLATION") == 0 && - pg_strcasecmp(prev2_wd, "LEVEL") == 0 && - pg_strcasecmp(prev_wd, "REPEATABLE") == 0) + else if (MATCHES4("SET|BEGIN|START|AS", "TRANSACTION|WORK", "ISOLATION", "LEVEL")) + COMPLETE_WITH_LIST3("READ", "REPEATABLE", "SERIALIZABLE"); + else if (MATCHES4("TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ")) + COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED"); + else if (MATCHES4("TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE")) COMPLETE_WITH_CONST("READ"); - else if ((pg_strcasecmp(prev3_wd, "SET") == 0 || - pg_strcasecmp(prev3_wd, "BEGIN") == 0 || - pg_strcasecmp(prev3_wd, "START") == 0 || - pg_strcasecmp(prev3_wd, "AS") == 0) && - (pg_strcasecmp(prev2_wd, "TRANSACTION") == 0 || - pg_strcasecmp(prev2_wd, "WORK") == 0) && - pg_strcasecmp(prev_wd, "READ") == 0) - { - static const char *const my_list[] = - {"ONLY", "WRITE", NULL}; - - COMPLETE_WITH_LIST(my_list); - } + else if (MATCHES3("SET|BEGIN|START|AS", "TRANSACTION|WORK", "READ")) + COMPLETE_WITH_LIST2("ONLY", "WRITE"); /* SET CONSTRAINTS */ - else if (pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev_wd, "CONSTRAINTS") == 0) - { + else if (MATCHES2("SET", "CONSTRAINTS")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'"); - } /* Complete SET CONSTRAINTS with DEFERRED|IMMEDIATE */ - else if (pg_strcasecmp(prev3_wd, "SET") == 0 && - pg_strcasecmp(prev2_wd, "CONSTRAINTS") == 0) - { - static const char *const constraint_list[] = - {"DEFERRED", "IMMEDIATE", NULL}; - - COMPLETE_WITH_LIST(constraint_list); - } + else if (MATCHES3("SET", "CONSTRAINTS", "")) + COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE"); /* Complete SET ROLE */ - else if (pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev_wd, "ROLE") == 0) + else if (MATCHES2("SET", "ROLE")) COMPLETE_WITH_QUERY(Query_for_list_of_roles); /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */ - else if (pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev_wd, "SESSION") == 0) - { - static const char *const my_list[] = - {"AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION", NULL}; - - COMPLETE_WITH_LIST(my_list); - } + else if (MATCHES2("SET", "SESSION")) + COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION"); /* Complete SET SESSION AUTHORIZATION with username */ - else if (pg_strcasecmp(prev3_wd, "SET") == 0 - && pg_strcasecmp(prev2_wd, "SESSION") == 0 - && pg_strcasecmp(prev_wd, "AUTHORIZATION") == 0) + else if (MATCHES3("SET", "SESSION", "AUTHORIZATION")) COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'"); /* Complete RESET SESSION with AUTHORIZATION */ - else if (pg_strcasecmp(prev2_wd, "RESET") == 0 && - pg_strcasecmp(prev_wd, "SESSION") == 0) + else if (MATCHES2("RESET", "SESSION")) COMPLETE_WITH_CONST("AUTHORIZATION"); /* Complete SET with "TO" */ - else if (pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev4_wd, "UPDATE") != 0 && - pg_strcasecmp(prev_wd, "TABLESPACE") != 0 && - pg_strcasecmp(prev_wd, "SCHEMA") != 0 && - prev_wd[strlen(prev_wd) - 1] != ')' && - prev_wd[strlen(prev_wd) - 1] != '=' && - pg_strcasecmp(prev4_wd, "DOMAIN") != 0) + else if (MATCHES3("", "SET", "")) COMPLETE_WITH_CONST("TO"); /* Suggest possible variable values */ - else if (pg_strcasecmp(prev3_wd, "SET") == 0 && - (pg_strcasecmp(prev_wd, "TO") == 0 || strcmp(prev_wd, "=") == 0)) + else if (MATCHES3("SET", "", "TO|=")) { - if (pg_strcasecmp(prev2_wd, "DateStyle") == 0) + if (MATCHES2("DateStyle", "TO|=")) { static const char *const my_list[] = {"ISO", "SQL", "Postgres", "German", @@ -3604,66 +2565,48 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(my_list); } - else if (pg_strcasecmp(prev2_wd, "IntervalStyle") == 0) - { - static const char *const my_list[] = - {"postgres", "postgres_verbose", "sql_standard", "iso_8601", NULL}; - - COMPLETE_WITH_LIST(my_list); - } - else if (pg_strcasecmp(prev2_wd, "GEQO") == 0) - { - static const char *const my_list[] = - {"ON", "OFF", "DEFAULT", NULL}; - - COMPLETE_WITH_LIST(my_list); - } - else if (pg_strcasecmp(prev2_wd, "search_path") == 0) - { + else if (MATCHES2("IntervalStyle", "TO|=")) + COMPLETE_WITH_LIST4("postgres", "postgres_verbose", "sql_standard", "iso_8601"); + else if (MATCHES2("GEQO", "TO|=")) + COMPLETE_WITH_LIST3("ON", "OFF", "DEFAULT"); + else if (MATCHES2("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' "); - } else - { - static const char *const my_list[] = - {"DEFAULT", NULL}; - - COMPLETE_WITH_LIST(my_list); - } + COMPLETE_WITH_CONST("DEFAULT"); } /* START TRANSACTION */ - else if (pg_strcasecmp(prev_wd, "START") == 0) + else if (MATCHES1("START")) COMPLETE_WITH_CONST("TRANSACTION"); /* TABLE, but not TABLE embedded in other commands */ - else if (pg_strcasecmp(prev_wd, "TABLE") == 0 && - prev2_wd[0] == '\0') + else if (MATCHES2("", "TABLE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL); /* TABLESAMPLE */ - else if (pg_strcasecmp(prev_wd, "TABLESAMPLE") == 0) + else if (MATCHES1("TABLESAMPLE")) COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods); - else if (pg_strcasecmp(prev2_wd, "TABLESAMPLE") == 0) + else if (MATCHES2("TABLESTAMPLE", "")) COMPLETE_WITH_CONST("("); /* TRUNCATE */ - else if (pg_strcasecmp(prev_wd, "TRUNCATE") == 0) + else if (MATCHES1("TRUNCATE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* UNLISTEN */ - else if (pg_strcasecmp(prev_wd, "UNLISTEN") == 0) + 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 '*'"); /* UPDATE */ /* If prev. word is UPDATE suggest a list of tables */ - else if (pg_strcasecmp(prev_wd, "UPDATE") == 0) + else if (MATCHES1("UPDATE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); /* Complete UPDATE
with "SET" */ - else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0) + else if (MATCHES2("UPDATE", "
")) COMPLETE_WITH_CONST("SET"); /* @@ -3671,83 +2614,54 @@ psql_completion(const char *text, int start, int end) * word) the word before it was (hopefully) a table name and we'll now * make a list of attributes. */ - else if (pg_strcasecmp(prev_wd, "SET") == 0) + else if (MATCHES1("SET")) COMPLETE_WITH_ATTR(prev2_wd, ""); /* UPDATE xx SET yy = */ - else if (pg_strcasecmp(prev2_wd, "SET") == 0 && - pg_strcasecmp(prev4_wd, "UPDATE") == 0) + else if (MATCHES4("UPDATE", "
", "SET", "")) COMPLETE_WITH_CONST("="); /* USER MAPPING */ - else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 || - pg_strcasecmp(prev3_wd, "CREATE") == 0 || - pg_strcasecmp(prev3_wd, "DROP") == 0) && - pg_strcasecmp(prev2_wd, "USER") == 0 && - pg_strcasecmp(prev_wd, "MAPPING") == 0) + else if (MATCHES3("ALTER|CREATE|DROP", "USER", "MAPPING")) COMPLETE_WITH_CONST("FOR"); - else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && - pg_strcasecmp(prev3_wd, "USER") == 0 && - pg_strcasecmp(prev2_wd, "MAPPING") == 0 && - pg_strcasecmp(prev_wd, "FOR") == 0) + 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'"); - else if ((pg_strcasecmp(prev4_wd, "ALTER") == 0 || - pg_strcasecmp(prev4_wd, "DROP") == 0) && - pg_strcasecmp(prev3_wd, "USER") == 0 && - pg_strcasecmp(prev2_wd, "MAPPING") == 0 && - pg_strcasecmp(prev_wd, "FOR") == 0) + else if (MATCHES4("ALTER|DROP", "USER", "MAPPING", "FOR")) COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings); - else if ((pg_strcasecmp(prev5_wd, "CREATE") == 0 || - pg_strcasecmp(prev5_wd, "ALTER") == 0 || - pg_strcasecmp(prev5_wd, "DROP") == 0) && - pg_strcasecmp(prev4_wd, "USER") == 0 && - pg_strcasecmp(prev3_wd, "MAPPING") == 0 && - pg_strcasecmp(prev2_wd, "FOR") == 0) + else if (MATCHES5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", "")) COMPLETE_WITH_CONST("SERVER"); /* * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ] * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ] */ - else if (pg_strcasecmp(prev_wd, "VACUUM") == 0) + 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'"); - else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 && - (pg_strcasecmp(prev_wd, "FULL") == 0 || - pg_strcasecmp(prev_wd, "FREEZE") == 0)) + else if (MATCHES2("VACUUM", "FULL|FREEZE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, " UNION SELECT 'ANALYZE'" " UNION SELECT 'VERBOSE'"); - else if (pg_strcasecmp(prev3_wd, "VACUUM") == 0 && - pg_strcasecmp(prev_wd, "ANALYZE") == 0 && - (pg_strcasecmp(prev2_wd, "FULL") == 0 || - pg_strcasecmp(prev2_wd, "FREEZE") == 0)) + else if (MATCHES3("VACUUM", "FULL|FREEZE", "ANALYZE|ANALYSE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, " UNION SELECT 'VERBOSE'"); - else if (pg_strcasecmp(prev3_wd, "VACUUM") == 0 && - pg_strcasecmp(prev_wd, "VERBOSE") == 0 && - (pg_strcasecmp(prev2_wd, "FULL") == 0 || - pg_strcasecmp(prev2_wd, "FREEZE") == 0)) + else if (MATCHES3("VACUUM", "FULL|FREEZE", "VERBOSE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, " UNION SELECT 'ANALYZE'"); - else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 && - pg_strcasecmp(prev_wd, "VERBOSE") == 0) + else if MATCHES2("VACUUM", "VERBOSE") COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, " UNION SELECT 'ANALYZE'"); - else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 && - pg_strcasecmp(prev_wd, "ANALYZE") == 0) + else if (MATCHES2("VACUUM", "ANALYZE|ANALYSE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, " UNION SELECT 'VERBOSE'"); - else if ((pg_strcasecmp(prev_wd, "ANALYZE") == 0 && - pg_strcasecmp(prev2_wd, "VERBOSE") == 0) || - (pg_strcasecmp(prev_wd, "VERBOSE") == 0 && - pg_strcasecmp(prev2_wd, "ANALYZE") == 0)) + else if (MATCHES2("VERBOSE", "ANALYZE|ANALYSE") || + MATCHES2("ANALYZE|ANALYSE", "VERBOSE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL); /* WITH [RECURSIVE] */ @@ -3756,29 +2670,26 @@ psql_completion(const char *text, int start, int end) * Only match when WITH is the first word, as WITH may appear in many * other contexts. */ - else if (pg_strcasecmp(prev_wd, "WITH") == 0 && - prev2_wd[0] == '\0') + else if (MATCHES2("", "WITH")) COMPLETE_WITH_CONST("RECURSIVE"); /* ANALYZE */ /* If the previous word is ANALYZE, produce list of tables */ - else if (pg_strcasecmp(prev_wd, "ANALYZE") == 0) + else if (MATCHES1("ANALYZE|ANALYSE")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL); /* WHERE */ /* Simple case of the word before the where being the table name */ - else if (pg_strcasecmp(prev_wd, "WHERE") == 0) + else if (MATCHES1("WHERE")) COMPLETE_WITH_ATTR(prev2_wd, ""); /* ... FROM ... */ /* TODO: also include SRF ? */ - else if (pg_strcasecmp(prev_wd, "FROM") == 0 && - pg_strcasecmp(prev3_wd, "COPY") != 0 && - pg_strcasecmp(prev3_wd, "\\copy") != 0) + else if (MATCHES3("COPY|\\copy", "", "FROM")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL); /* ... JOIN ... */ - else if (pg_strcasecmp(prev_wd, "JOIN") == 0) + else if (MATCHES1("JOIN")) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL); /* Backslash commands */