Making tab-complete.c easier to maintain
Hi hackers,
After spending some time in tab-complete.c responding to a bug report, I
had very strong urge to find a way to make it a bit easier to maintain. Do
you think it would be an improvement if we changed all the code that looks
a bit like this:
/* Complete CREATE TRIGGER <name> 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);
}
... into code that looks a bit like this?
/* Complete CREATE TRIGGER <name> BEFORE|AFTER with an event */
else if (MATCHES4("CREATE", "TRIGGER", "<name>", "BEFORE|AFTER"))
COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
See attached a proof-of-concept patch. It reduces the size of
tab-complete.c by a bit over a thousand lines. I realise that changing so
many lines just to refactor code may may be a difficult sell! But I think
this would make it easier to improve the tab completion code in future, and
although it's large it's a superficial and mechanical change.
--
Thomas Munro
http://www.enterprisedb.com
Attachments:
tab-complete-macrology.patchapplication/octet-stream; name=tab-complete-macrology.patchDownload
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("<foo>", ""));
+ Assert(word_matches("<foo>", "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", "<sth>", "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", "<name>"))
{
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 <name> */
- 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", "<name>"))
COMPLETE_WITH_CONST("(");
/* ALTER AGGREGATE,FUNCTION <name> (...) */
- 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", "<name>", "<...>"))
{
- 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 <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
/* ALTER COLLATION <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER CONVERSION <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER DATABASE <name> */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "DATABASE") == 0)
+ else if (MATCHES3("ALTER", "DATABASE", "<name>"))
{
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 <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
/* ALTER EVENT TRIGGER <name> 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", "<name>", "ENABLE"))
+ COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
/* ALTER EXTENSION <name> */
- 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 <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST4("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO");
/* ALTER FOREIGN TABLE <name> */
- 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", "<name>"))
{
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 <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
/* ALTER INDEX <name> 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", "<name>", "SET"))
+ COMPLETE_WITH_LIST2("(", "TABLESPACE");
/* ALTER INDEX <name> 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", "<name>", "RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER INDEX <foo> 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", "<name>", "SET|RESET", "("))
+ COMPLETE_WITH_LIST3("fillfactor", "fastupdate", "gin_pending_list_limit");
/* ALTER LANGUAGE <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
/* ALTER LARGE OBJECT <oid> */
- 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", "<oid>"))
+ 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 <name> */
- 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", "<name>") && !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 <name> 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", "<name>", "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 <name> 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", "<name>", "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", "<name>") ||
+ MATCHES5("DEFAULT", "PRIVILEGES", "IN", "SCHEMA", "<name>"))
+ COMPLETE_WITH_LIST2("GRANT", "REVOKE");
/* ALTER DOMAIN <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT");
/* ALTER DOMAIN <sth> 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", "<sth>", "DROP"))
+ COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
/* ALTER DOMAIN <sth> 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", "<sth>", "DROP|RENAME|VALIDATE", "CONSTRAINT"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
}
/* ALTER DOMAIN <sth> 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", "<name>", "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 <sth> RENAME CONSTRAINT <sth> */
- 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", "<sth>"))
COMPLETE_WITH_CONST("TO");
/* ALTER DOMAIN <sth> 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", "<sth>", "SET"))
+ COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
/* ALTER SEQUENCE <name> */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "SEQUENCE") == 0)
+ else if (MATCHES3("ALTER", "SEQUENCE", "<name>"))
{
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 <name> 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", "<name>", "NO"))
+ COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
/* ALTER SERVER <name> */
- 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", "<name>"))
+ 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 <name> */
- 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", "<name>"))
COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
/* ALTER VIEW <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER MATERIALIZED VIEW <name> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER POLICY <name> ON */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "POLICY") == 0)
+ else if (MATCHES3("ALTER", "POLICY", "<name>"))
COMPLETE_WITH_CONST("ON");
/* ALTER POLICY <name> ON <table> */
- 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", "<name>", "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* ALTER POLICY <name> ON <table> - 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", "<name>", "ON", "<table>"))
+ COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING", "WITH CHECK");
/* ALTER POLICY <name> ON <table> TO <role> */
- 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", "<name>", "ON", "<table>", "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
/* ALTER POLICY <name> ON <table> 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", "<name>", "ON", "<table>", "USING"))
COMPLETE_WITH_CONST("(");
/* ALTER POLICY <name> ON <table> 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", "<name>", "ON", "<table>", "WITH", "CHECK"))
COMPLETE_WITH_CONST("(");
/* ALTER RULE <name>, add ON */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "RULE") == 0)
+ else if (MATCHES3("ALTER", "RULE", "<name>"))
COMPLETE_WITH_CONST("ON");
/* If we have ALTER RULE <name> 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", "<name>", "ON"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
}
/* ALTER RULE <name> ON <name> */
- else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev4_wd, "RULE") == 0)
+ else if (MATCHES5("ALTER", "RULE", "<name>", "ON", "<name>"))
COMPLETE_WITH_CONST("RENAME TO");
/* ALTER TRIGGER <name>, add ON */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "TRIGGER") == 0)
+ else if (MATCHES3("ALTER", "TRIGGER", "<name>"))
COMPLETE_WITH_CONST("ON");
- else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev3_wd, "TRIGGER") == 0)
+ else if (MATCHES4("ALTER", "TRIGGER", "<name>", "<sth>"))
{
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 <sth> 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", "<sth>", "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* ALTER TRIGGER <name> ON <name> */
- 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", "<name>", "ON", "<name>"))
COMPLETE_WITH_CONST("RENAME TO");
/*
* If we detect ALTER TABLE <name>, suggest sub commands
*/
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "TABLE") == 0)
+ else if (MATCHES3("ALTER", "TABLE", "<name>"))
{
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", "<name>", "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", "<name>", "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", "<name>", "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", "<name>", "ENABLE", "<sth>", "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", "<name>", "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", "<name>", "ENABLE", "<sth>", "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", "<name>", "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", "<name>", "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", "<name>", "DISABLE"))
+ COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
+ else if (MATCHES5("ALTER", "TABLE", "<name>", "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", "<name>", "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", "<name>", "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", "<name>", "RENAME"))
COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
/*
* If we have TABLE <sth> 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", "<name>", "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", "<name>", "RENAME", "<name>") &&
+ !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", "<name>", "RENAME", "COLUMN|CONSTRAINT", "<name>") &&
+ !MATCHES1("TO"))
COMPLETE_WITH_CONST("TO");
/* If we have TABLE <sth> 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", "<name>", "DROP"))
+ COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
/* If we have ALTER TABLE <sth> 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", "<name>", "DROP", "COLUMN"))
COMPLETE_WITH_ATTR(prev3_wd, "");
/*
* If we have ALTER TABLE <sth> 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", "<name>", "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
}
/* ALTER TABLE ALTER [COLUMN] <foo> */
- 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", "<name>") ||
+ MATCHES4("TABLE", "<name>", "ALTER", "<name>"))
+ COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
/* ALTER TABLE ALTER [COLUMN] <foo> 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", "<name>", "SET") ||
+ MATCHES5("TABLE", "<name>", "ALTER", "<name>", "SET"))
+ COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
/* ALTER TABLE ALTER [COLUMN] <foo> 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", "<name>", "SET", "(") ||
+ MATCHES4("ALTER", "<name>", "SET", "("))
+ COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
/* ALTER TABLE ALTER [COLUMN] <foo> 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", "<name>", "SET", "STORAGE") ||
+ MATCHES4("ALTER", "<name>", "SET", "STORAGE"))
+ COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
/* ALTER TABLE ALTER [COLUMN] <foo> 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", "<name>", "DROP") ||
+ MATCHES5("TABLE", "<name>", "ALTER", "<name>", "DROP"))
+ COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
+ else if (MATCHES3("TABLE", "<name>", "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", "<name>", "CLUSTER", "ON"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_index_of_table);
}
/* If we have TABLE <sth> 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", "<name>", "SET"))
+ COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT");
/* If we have TABLE <sth> 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", "<name>", "SET", "TABLESPACE"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
/* If we have TABLE <sth> 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", "<name>", "SET", "WITHOUT"))
+ COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
/* ALTER TABLE <foo> RESET */
- else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
- pg_strcasecmp(prev_wd, "RESET") == 0)
+ else if (MATCHES3("TABLE", "<name>", "RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER TABLE <foo> 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", "<name>", "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", "<name>", "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", "<name>", "REPLICA", "IDENTITY"))
+ COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
+ else if (MATCHES3("TABLE", "<name>", "REPLICA"))
COMPLETE_WITH_CONST("IDENTITY");
- }
/* ALTER TABLESPACE <foo> 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", "<name>"))
+ COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
/* ALTER TABLESPACE <foo> 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", "<name>", "SET|RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER TABLESPACE <foo> 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", "<name>", "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", "<name>"))
+ COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
+ else if (MATCHES5("ALTER", "TEXT", "SEARCH", "DICTIONARY", "<name>"))
+ COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
+ else if (MATCHES5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", "<name>"))
+ COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING", "DROP MAPPING FOR",
+ "OWNER TO", "RENAME TO", "SET SCHEMA");
/* complete ALTER TYPE <foo> 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", "<name>"))
+ COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
+ "DROP ATTRIBUTE", "OWNER TO", "RENAME", "SET SCHEMA");
/* complete ALTER TYPE <foo> 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", "<name>", "ADD"))
+ COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
/* ALTER TYPE <foo> 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", "<name>", "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", "<name>", "RENAME", "ATTRIBUTE", "<name>"))
COMPLETE_WITH_CONST("TO");
/*
* If we have TYPE <sth> 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", "<name>", "ALTER|DROP|RENAME", "ATTRIBUTE"))
COMPLETE_WITH_ATTR(prev3_wd, "");
/* ALTER TYPE ALTER ATTRIBUTE <foo> */
- else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "ATTRIBUTE") == 0))
- {
+ else if (MATCHES3("ALTER", "ATTRIBUTE", "<name>"))
COMPLETE_WITH_CONST("TYPE");
- }
/* complete ALTER GROUP <foo> */
- 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", "<name>"))
+ COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
/* complete ALTER GROUP <foo> 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", "<name>", "ADD|DROP"))
COMPLETE_WITH_CONST("USER");
/* complete {ALTER} GROUP <foo> 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", "<name>", "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 <sth>, 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", "<sth>") && !MATCHES1("VERBOSE"))
COMPLETE_WITH_CONST("USING");
- }
/* If we have CLUSTER VERBOSE <sth>, then add "USING" */
- else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 &&
- pg_strcasecmp(prev2_wd, "VERBOSE") == 0)
- {
+ else if (MATCHES3("CLUSTER", "VERBOSE", "<sth>"))
COMPLETE_WITH_CONST("USING");
- }
/*
* If we have CLUSTER <sth> 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", "<sth>", "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 <sth> 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", "<sth>", "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", "<name>"))
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", "<name>", "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", "<sth>", "<sth>") ||
+ MATCHES5("COMMENT", "ON", "<sth>", "<sth>", "<sth>") ||
+ MATCHES6("COMMENT", "ON", "<sth>", "<sth>", "<sth>", "<sth>")) &&
+ !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 <sth>, 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", "<sth>"))
+ COMPLETE_WITH_LIST2("FROM", "TO");
/* If we have COPY|BINARY <sth> 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", "<sth>", "FROM|TO"))
{
completion_charp = "";
matches = completion_matches(text, complete_from_files);
}
/* Handle COPY|BINARY <sth> 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", "<sth>", "FROM|TO", "<filename>"))
+ COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV", "ENCODING");
/* Handle COPY|BINARY <sth> 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", "<filename>", "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", "<name>"))
{
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", "<name>", "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 <name> */
- else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev2_wd, "EXTENSION") == 0)
+ else if (MATCHES3("CREATE", "EXTENSION", "<name>"))
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", "<name>"))
+ 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 [<name>] 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", "<name>", "ON") ||
+ MATCHES2("INDEX|CONCURRENTLY", "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
/* If we have CREATE|UNIQUE INDEX <sth> 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", "<name>", "CONCURRENTLY") ||
+ MATCHES2("INDEX", "CONCURRENTLY"))
COMPLETE_WITH_CONST("ON");
/* If we have CREATE|UNIQUE INDEX <sth>, 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", "<sth>"))
+ COMPLETE_WITH_LIST2("CONCURRENTLY", "ON");
/*
* Complete INDEX <name> ON <table> 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", "<name>", "ON", "<name>") ||
+ MATCHES3("INDEX|CONCURRENTLY", "ON", "<name>"))
+ COMPLETE_WITH_LIST2("(", "USING");
+ else if (MATCHES5("INDEX", "<name>", "ON", "<name>", "(") ||
+ MATCHES4("INDEX|CONCURRENTLY", "ON", "<name>", "("))
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", "<name>", "USING", "<name>", "("))
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", "<sth>", "<sth>", "ON", "<name>", "USING") ||
+ MATCHES5("INDEX", "<sth>", "ON", "<name>", "USING") ||
+ MATCHES4("INDEX", "ON", "<name>", "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", "<sth>", "USING", "<sth>") &&
+ !MATCHES6("POLICY", "<sth>", "<sth>", "<sth>", "<sth>", "<sth>") &&
+ !MATCHES4("FOR", "<sth>", "<sth>", "<sth>"))
COMPLETE_WITH_CONST("(");
/* CREATE POLICY */
/* Complete "CREATE POLICY <name> ON" */
- else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev2_wd, "POLICY") == 0)
+ else if (MATCHES3("CREATE", "POLICY", "<name>"))
COMPLETE_WITH_CONST("ON");
/* Complete "CREATE POLICY <name> ON <table>" */
- 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", "<name>", "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* Complete "CREATE POLICY <name> ON <table> 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", "<name>", "ON", "<table>"))
+ COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
/*
* Complete "CREATE POLICY <name> ON <table> 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", "<name>", "ON", "<table>", "FOR"))
+ COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
/* Complete "CREATE POLICY <name> ON <table> 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", "<name>", "ON", "<table>", "FOR", "INSERT"))
+ COMPLETE_WITH_LIST2("TO", "WITH CHECK");
/*
* Complete "CREATE POLICY <name> ON <table> FOR SELECT TO|USING" Complete
* "CREATE POLICY <name> ON <table> 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", "<name>", "ON", "<table>", "FOR", "SELECT|DELETE"))
+ COMPLETE_WITH_LIST2("TO", "USING");
/*
* Complete "CREATE POLICY <name> ON <table> FOR ALL TO|USING|WITH CHECK"
* Complete "CREATE POLICY <name> ON <table> 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", "<name>", "ON", "<table>", "FOR", "ALL|UPDATE"))
+ COMPLETE_WITH_LIST3("TO", "USING", "WITH CHECK");
/* Complete "CREATE POLICY <name> ON <table> TO <role>" */
- 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", "<name>", "ON", "<table>", "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
/* Complete "CREATE POLICY <name> ON <table> 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", "<name>", "ON", "<table>", "USING"))
COMPLETE_WITH_CONST("(");
/* CREATE RULE */
/* Complete "CREATE RULE <sth>" with "AS" */
- else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev2_wd, "RULE") == 0)
+ else if (MATCHES3("CREATE", "RULE", "<sth>"))
COMPLETE_WITH_CONST("AS");
/* Complete "CREATE RULE <sth> 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", "<sth>", "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", "<sth>", "AS", "ON"))
+ COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
/* Complete "AS ON <sth with a 'T' :)>" 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 <sth> 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 <name> */
- 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", "<name>") ||
+ MATCHES4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", "<name>"))
+ COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
+ "CYCLE", "OWNED BY", "START WITH");
/* CREATE TEMP/TEMPORARY SEQUENCE <name> 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", "<name>", "NO") ||
+ MATCHES5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", "<name>", "NO"))
+ COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
/* CREATE SERVER <name> */
- 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", "<name>"))
+ 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", "<name>"))
+ 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", "<name>", "OWNER", "<name>"))
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", "<sth>"))
COMPLETE_WITH_CONST("(");
/* CREATE TRIGGER */
/* complete CREATE TRIGGER <name> 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", "<name>"))
+ COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
/* complete CREATE TRIGGER <name> 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", "<name>", "BEFORE|AFTER"))
+ COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
/* complete CREATE TRIGGER <name> 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", "<name>", "INSTEAD", "OF"))
+ COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
/* complete CREATE TRIGGER <name> 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", "<name>", "BEFORE|AFTER", "<sth>") ||
+ MATCHES6("CREATE", "TRIGGER", "<name>", "INSTEAD", "OF", "<sth>"))
+ COMPLETE_WITH_LIST2("ON", "OR");
/*
* complete CREATE TRIGGER <name> 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", "<name>", "BEFORE|AFTER", "<event>", "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", "<event>", "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 <name> */
- 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", "<name>") &&
+ !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 <name> 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", "<name>", "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 <name> 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", "<name>", "ENCRYPTED|UNENCRYPTED"))
COMPLETE_WITH_CONST("PASSWORD");
- }
/* complete CREATE ROLE,USER,GROUP <name> 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", "<name>", "IN"))
+ COMPLETE_WITH_LIST2("GROUP", "ROLE");
/* CREATE VIEW */
/* Complete CREATE VIEW <name> with AS */
- else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev2_wd, "VIEW") == 0)
+ else if (MATCHES3("CREATE", "VIEW", "<name>"))
COMPLETE_WITH_CONST("AS");
/* Complete "CREATE VIEW <sth> 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", "<name>", "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 <name> 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 <sth> 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", "<name>", "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 <name> 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", "<name>"))
COMPLETE_WITH_CONST("ON");
/* Complete CREATE EVENT TRIGGER <name> 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", "<name>", "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", "<name>"))
+ 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 <table> */
- 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", "<table>"))
+ 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", "<name>"))
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",
+ "<name>") ||
+ (MATCHES4("DROP", "AGGREGATE", "<name>", "<sth>") && ends_with(prev_wd, ')')) ||
+ MATCHES4("DROP", "EVENT", "TRIGGER", "<name>") ||
+ MATCHES5("DROP", "FOREIGN", "DATA", "WRAPPER", "<name>") ||
+ MATCHES5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", "<name>"))
+ {
+ if (MATCHES3("DROP", "FUNCTION", "<name>"))
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", "<name>", "("))
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", "<name>"))
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", "<name>", "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", "<name>", "ON", "<name>"))
+ 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 <name> */
- 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 <name> ON */
- else if (pg_strcasecmp(prev3_wd, "DROP") == 0 &&
- pg_strcasecmp(prev2_wd, "POLICY") == 0)
- {
+ else if (MATCHES3("DROP", "POLICY", "<name>"))
COMPLETE_WITH_CONST("ON");
- }
/* DROP POLICY <name> ON <table> */
- 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", "<name>", "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", "<name>"))
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", "<name>", "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", "<name>", "ON", "<name>"))
+ 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 <sth> 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", "<sth>"))
+ COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
/*
* Complete FETCH <sth1> <sth2> 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", "<sth1>", "<sth2>"))
+ 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 <privilege> with "ON", GRANT/REVOKE <role> with
* TO/FROM
*/
- else if (pg_strcasecmp(prev2_wd, "GRANT") == 0 ||
- pg_strcasecmp(prev2_wd, "REVOKE") == 0)
+ else if (MATCHES2("GRANT|REVOKE", "<privilege>"))
{
- 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", "<privilege>"))
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", "<sth>", "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", "<sth>", "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", "<sth>", "ON", "<name>"))
{
- 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", "<sth>", "<sth>", "<sth>"))
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", "<sth>", "ON", "<sth>", "<sth>"))
{
- 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", "<sth>", "ON", "<sth>", "<sth>"))
{
- 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", "<sth>", "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", "<sth>", "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", "<sth>", "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 <table> (" 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", "<table>", "("))
COMPLETE_WITH_ATTR(prev2_wd, "");
/*
* Complete INSERT INTO <table> 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", "<table>"))
+ COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
/*
* Complete INSERT INTO <table> (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", "<table>", "<?>") && 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] <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", "<table>") && !MATCHES2("LOCK", "TABLE")) ||
+ MATCHES3("LOCK", "TABLE", "<table>"))
COMPLETE_WITH_CONST("IN");
/* Complete LOCK [TABLE] <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", "<table>", "IN") ||
+ MATCHES4("LOCK", "TABLE", "<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", "<sth>", "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", "<sth>", "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", "<name>", "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", "<name>"))
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", "<name>", "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", "<name>"))
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", "<name>"))
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", "<name>", "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", "<name>", "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", "<name>", "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", "<sth>"))
{
- 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", "<name>"))
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", "<sth>", "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", "<sth>", "<sth>"))
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 <foo> 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", "<foo>"))
+ 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 <var> 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", "<var>"))
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", "<var>", "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", "<method>"))
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 <table> with "SET" */
- else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0)
+ else if (MATCHES2("UPDATE", "<table>"))
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", "<table>", "SET", "<sth>"))
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", "<sth>"))
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", "<sth>", "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 */
Thomas Munro <thomas.munro@enterprisedb.com> writes:
See attached a proof-of-concept patch. It reduces the size of
tab-complete.c by a bit over a thousand lines. I realise that changing so
many lines just to refactor code may may be a difficult sell! But I think
this would make it easier to improve the tab completion code in future, and
although it's large it's a superficial and mechanical change.
I really dislike the magical "<" business. Maybe you could use NULL
instead of having to reserve a class of real strings as placeholders.
(That would require finding another way to denote the end of the list,
but a separate count argument seems like a possible answer.)
Or perhaps use empty strings as placeholders?
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sat, Sep 5, 2015 at 1:40 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
Thomas Munro <thomas.munro@enterprisedb.com> writes:
See attached a proof-of-concept patch. It reduces the size of
tab-complete.c by a bit over a thousand lines. I realise that changingso
many lines just to refactor code may may be a difficult sell! But I
think
this would make it easier to improve the tab completion code in future,
and
although it's large it's a superficial and mechanical change.
I really dislike the magical "<" business. Maybe you could use NULL
instead of having to reserve a class of real strings as placeholders.
Thanks, good point. Here's a version that uses NULL via a macro ANY.
Aside from a few corrections it also now distinguishes between
TAIL_MATCHESn (common) and MATCHESn (rarely used for now), for example:
/* 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)
- {
- static const char *const list_ALTERALLINTSPC[] =
- {"SET TABLESPACE", "OWNED BY", NULL};
-
- COMPLETE_WITH_LIST(list_ALTERALLINTSPC);
- }
+ else if (TAIL_MATCHES4("ALL", "IN", "TABLESPACE", ANY))
+ COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
... versus:
/* EXECUTE, but not EXECUTE embedded in other commands */
- else if (pg_strcasecmp(prev_wd, "EXECUTE") == 0 &&
- prev2_wd[0] == '\0')
+ else if (MATCHES1("EXECUTE"))
COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
--
Thomas Munro
http://www.enterprisedb.com
Attachments:
tab-complete-macrology-v2.patchapplication/octet-stream; name=tab-complete-macrology-v2.patchDownload
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 816deda..08029f9 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,59 @@ initialize_readline(void)
*/
}
+/*
+ * Check if 'word' matches any of the '|'-separated strings in 'pattern',
+ * using case-insensitive comparison, or the pattern is NULL indicating a
+ * wildcard that matches any word.
+ */
+static bool
+word_matches(const char *pattern, const char *word)
+{
+ const char *c = word;
+
+ /*
+ * NULL means match any word, but we don't match empty strings because
+ * they indicate that the [END_]MATCHESn macro is trying to look before
+ * the start of the user's input string.
+ */
+ if (pattern == NULL)
+ return word[0] != '\0';
+
+ 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 +1007,66 @@ psql_completion(const char *text, int start, int end)
#define prev5_wd (previous_words[4])
#define prev6_wd (previous_words[5])
+#define ANY NULL
+
+#define TAIL_MATCHES1(p1) \
+(word_matches(p1, prev_wd)) \
+
+#define TAIL_MATCHES2(p2, p1) \
+(word_matches(p1, prev_wd) && \
+ word_matches(p2, prev2_wd))
+
+#define TAIL_MATCHES3(p3, p2, p1) \
+(word_matches(p1, prev_wd) && \
+ word_matches(p2, prev2_wd) && \
+ word_matches(p3, prev3_wd))
+
+#define TAIL_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 TAIL_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 TAIL_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 TAIL_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 TAIL_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))
+
+#define MATCHES1(p1) TAIL_MATCHES2("", p1)
+#define MATCHES2(p1, p2) TAIL_MATCHES3("", p1, p2)
+#define MATCHES3(p1, p2, p3) TAIL_MATCHES4("", p1, p2, p3)
+#define MATCHES4(p1, p2, p3, p4) TAIL_MATCHES5("", p1, p2, p3, p4)
+#define MATCHES5(p1, p2, p3, p4, p5) TAIL_MATCHES6("", p1, p2, p3, p4, p5)
+
static const char *const sql_commands[] = {
"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
"COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
@@ -931,6 +1100,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(NULL, ""));
+ Assert(word_matches(NULL, "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 temporary */
+
/* Clear a few things. */
completion_charp = NULL;
completion_charpp = NULL;
@@ -960,36 +1145,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 (TAIL_MATCHES1(""))
COMPLETE_WITH_LIST(sql_commands);
/* CREATE */
/* complete with something you can create */
- else if (pg_strcasecmp(prev_wd, "CREATE") == 0)
+ else if (TAIL_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 (MATCHES1("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 (TAIL_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 (TAIL_MATCHES1("ALTER") && !TAIL_MATCHES3("TABLE", ANY, "ALTER"))
{
static const char *const list_ALTER[] =
{"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
@@ -1002,153 +1182,67 @@ 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)
- {
- static const char *const list_ALTERALLINTSPC[] =
- {"SET TABLESPACE", "OWNED BY", NULL};
-
- COMPLETE_WITH_LIST(list_ALTERALLINTSPC);
- }
+ else if (TAIL_MATCHES4("ALL", "IN", "TABLESPACE", ANY))
+ COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
/* ALTER TABLE,INDEX,MATERIALIZED VIEW xxx ALL IN TABLESPACE xxx OWNED BY */
- else if (pg_strcasecmp(prev6_wd, "ALL") == 0 &&
- pg_strcasecmp(prev5_wd, "IN") == 0 &&
- pg_strcasecmp(prev4_wd, "TABLESPACE") == 0 &&
- pg_strcasecmp(prev2_wd, "OWNED") == 0 &&
- pg_strcasecmp(prev4_wd, "BY") == 0)
- {
+ else if (TAIL_MATCHES6("ALL", "IN", "TABLESPACE", ANY, "OWNED", "BY"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
- }
/* ALTER AGGREGATE,FUNCTION <name> */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- (pg_strcasecmp(prev2_wd, "AGGREGATE") == 0 ||
- pg_strcasecmp(prev2_wd, "FUNCTION") == 0))
+ else if (TAIL_MATCHES3("ALTER", "AGGREGATE|FUNCTION", ANY))
COMPLETE_WITH_CONST("(");
/* ALTER AGGREGATE,FUNCTION <name> (...) */
- else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
- (pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 ||
- pg_strcasecmp(prev3_wd, "FUNCTION") == 0))
+ else if (TAIL_MATCHES4("ALTER", "AGGREGATE|FUNCTION", ANY, ANY))
{
- if (prev_wd[strlen(prev_wd) - 1] == ')')
- {
- static const char *const list_ALTERAGG[] =
- {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL};
-
- COMPLETE_WITH_LIST(list_ALTERAGG);
- }
+ if (ends_with(prev_wd, ')'))
+ COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
else
COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
}
/* ALTER SCHEMA <name> */
- 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 (TAIL_MATCHES3("ALTER", "SCHEMA", ANY))
+ COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
/* ALTER COLLATION <name> */
- 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 (TAIL_MATCHES3("ALTER", "COLLATION", ANY))
+ COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER CONVERSION <name> */
- 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 (TAIL_MATCHES3("ALTER", "CONVERSION", ANY))
+ COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER DATABASE <name> */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "DATABASE") == 0)
- {
- static const char *const list_ALTERDATABASE[] =
- {"RESET", "SET", "OWNER TO", "RENAME TO", "IS_TEMPLATE",
- "ALLOW_CONNECTIONS", "CONNECTION LIMIT", NULL};
-
- COMPLETE_WITH_LIST(list_ALTERDATABASE);
- }
+ else if (TAIL_MATCHES3("ALTER", "DATABASE", ANY))
+ COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
+ "IS_TEMPLATE", "ALLOW_CONNECTIONS",
+ "CONNECTION LIMIT");
/* 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 (TAIL_MATCHES3("ALTER", "EVENT", "TRIGGER"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
- }
/* ALTER EVENT TRIGGER <name> */
- 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 (TAIL_MATCHES4("ALTER", "EVENT", "TRIGGER", ANY))
+ COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
/* ALTER EVENT TRIGGER <name> 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 (TAIL_MATCHES5("ALTER", "EVENT", "TRIGGER", ANY, "ENABLE"))
+ COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
/* ALTER EXTENSION <name> */
- 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 (TAIL_MATCHES3("ALTER", "EXTENSION", ANY))
+ 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 (TAIL_MATCHES2("ALTER", "FOREIGN"))
+ COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
/* ALTER FOREIGN DATA WRAPPER <name> */
- 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 (TAIL_MATCHES5("ALTER", "FOREIGN", "DATA", "WRAPPER", ANY))
+ COMPLETE_WITH_LIST4("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO");
/* ALTER FOREIGN TABLE <name> */
- else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev3_wd, "FOREIGN") == 0 &&
- pg_strcasecmp(prev2_wd, "TABLE") == 0)
+ else if (TAIL_MATCHES4("ALTER", "FOREIGN", "TABLE", ANY))
{
static const char *const list_ALTER_FOREIGN_TABLE[] =
{"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
@@ -1159,84 +1253,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 (TAIL_MATCHES2("ALTER", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
"UNION SELECT 'ALL IN TABLESPACE'");
- }
/* ALTER INDEX <name> */
- 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 (TAIL_MATCHES3("ALTER", "INDEX", ANY))
+ COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
/* ALTER INDEX <name> 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 (TAIL_MATCHES4("ALTER", "INDEX", ANY, "SET"))
+ COMPLETE_WITH_LIST2("(", "TABLESPACE");
/* ALTER INDEX <name> RESET */
- else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev3_wd, "INDEX") == 0 &&
- pg_strcasecmp(prev_wd, "RESET") == 0)
+ else if (TAIL_MATCHES4("ALTER", "INDEX", ANY, "RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER INDEX <foo> 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 (TAIL_MATCHES5("ALTER", "INDEX", ANY, "SET|RESET", "("))
+ COMPLETE_WITH_LIST3("fillfactor", "fastupdate", "gin_pending_list_limit");
/* ALTER LANGUAGE <name> */
- 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 (TAIL_MATCHES3("ALTER", "LANGUAGE", ANY))
+ COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
/* ALTER LARGE OBJECT <oid> */
- 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 (TAIL_MATCHES4("ALTER", "LARGE", "OBJECT", ANY))
+ 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 (TAIL_MATCHES3("ALTER", "MATERIALIZED", "VIEW"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
"UNION SELECT 'ALL IN TABLESPACE'");
- }
/* ALTER USER,ROLE <name> */
- 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 (TAIL_MATCHES3("ALTER", "USER|ROLE", ANY) && !TAIL_MATCHES2("USER", "MAPPING"))
{
static const char *const list_ALTERUSER[] =
{"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
@@ -1250,10 +1297,7 @@ psql_completion(const char *text, int start, int end)
}
/* ALTER USER,ROLE <name> 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 (TAIL_MATCHES4("ALTER", "USER|ROLE", ANY, "WITH"))
{
/* Similar to the above, but don't complete "WITH" again. */
static const char *const list_ALTERUSER_WITH[] =
@@ -1268,78 +1312,32 @@ psql_completion(const char *text, int start, int end)
}
/* complete ALTER USER,ROLE <name> 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 (TAIL_MATCHES4("ALTER", "USER|ROLE", ANY, "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 (TAIL_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 (TAIL_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 (TAIL_MATCHES5("DEFAULT", "PRIVILEGES", "FOR", "ROLE", ANY) ||
+ TAIL_MATCHES5("DEFAULT", "PRIVILEGES", "IN", "SCHEMA", ANY))
+ COMPLETE_WITH_LIST2("GRANT", "REVOKE");
/* ALTER DOMAIN <name> */
- 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 (TAIL_MATCHES3("ALTER", "DOMAIN", ANY))
+ COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT");
/* ALTER DOMAIN <sth> 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 (TAIL_MATCHES4("ALTER", "DOMAIN", ANY, "DROP"))
+ COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
/* ALTER DOMAIN <sth> 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 (TAIL_MATCHES5("ALTER", "DOMAIN", ANY, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
}
/* ALTER DOMAIN <sth> RENAME */
- else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev3_wd, "DOMAIN") == 0 &&
- pg_strcasecmp(prev_wd, "RENAME") == 0)
+ else if (TAIL_MATCHES4("ALTER", "DOMAIN", ANY, "RENAME"))
{
static const char *const list_ALTERDOMAIN[] =
{"CONSTRAINT", "TO", NULL};
@@ -1347,24 +1345,14 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_ALTERDOMAIN);
}
/* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
- else if (pg_strcasecmp(prev5_wd, "DOMAIN") == 0 &&
- pg_strcasecmp(prev3_wd, "RENAME") == 0 &&
- pg_strcasecmp(prev2_wd, "CONSTRAINT") == 0)
+ else if (TAIL_MATCHES3("RENAME", "CONSTRAINT", ANY))
COMPLETE_WITH_CONST("TO");
/* ALTER DOMAIN <sth> 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 (TAIL_MATCHES4("ALTER", "DOMAIN", ANY, "SET"))
+ COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
/* ALTER SEQUENCE <name> */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "SEQUENCE") == 0)
+ else if (TAIL_MATCHES3("ALTER", "SEQUENCE", ANY))
{
static const char *const list_ALTERSEQUENCE[] =
{"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
@@ -1373,123 +1361,63 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
}
/* ALTER SEQUENCE <name> 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 (TAIL_MATCHES4("ALTER", "SEQUEMCE", ANY, "NO"))
+ COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
/* ALTER SERVER <name> */
- 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 (TAIL_MATCHES3("ALTER", "SERVER", ANY))
+ 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 (TAIL_MATCHES2("ALTER", "SYSTEM"))
+ COMPLETE_WITH_LIST2("SET", "RESET");
/* ALTER SYSTEM SET|RESET <name> */
- 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 (TAIL_MATCHES4("ALTER", "SYSTEM", "SET|RESET", ANY))
COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
/* ALTER VIEW <name> */
- 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 (TAIL_MATCHES3("ALTER", "VIEW", ANY))
+ COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER MATERIALIZED VIEW <name> */
- 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 (TAIL_MATCHES4("ALTER", "MATERIALIZED", "VIEW", ANY))
+ COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER POLICY <name> ON */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "POLICY") == 0)
+ else if (TAIL_MATCHES3("ALTER", "POLICY", ANY))
COMPLETE_WITH_CONST("ON");
/* ALTER POLICY <name> ON <table> */
- else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev3_wd, "POLICY") == 0 &&
- pg_strcasecmp(prev_wd, "ON") == 0)
+ else if (TAIL_MATCHES4("ALTER", "POLICY", ANY, "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* ALTER POLICY <name> ON <table> - 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 (TAIL_MATCHES5("ALTER", "POLICY", ANY, "ON", ANY))
+ COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING", "WITH CHECK");
/* ALTER POLICY <name> ON <table> TO <role> */
- 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 (TAIL_MATCHES6("ALTER", "POLICY", ANY, "ON", ANY, "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
/* ALTER POLICY <name> ON <table> 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 (TAIL_MATCHES6("ALTER", "POLICY", ANY, "ON", ANY, "USING"))
COMPLETE_WITH_CONST("(");
/* ALTER POLICY <name> ON <table> 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 (TAIL_MATCHES6("POLICY", ANY, "ON", ANY, "WITH", "CHECK"))
COMPLETE_WITH_CONST("(");
/* ALTER RULE <name>, add ON */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "RULE") == 0)
+ else if (TAIL_MATCHES3("ALTER", "RULE", ANY))
COMPLETE_WITH_CONST("ON");
/* If we have ALTER RULE <name> 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 (TAIL_MATCHES4("ALTER", "RULE", ANY, "ON"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
}
/* ALTER RULE <name> ON <name> */
- else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev4_wd, "RULE") == 0)
+ else if (TAIL_MATCHES5("ALTER", "RULE", ANY, "ON", ANY))
COMPLETE_WITH_CONST("RENAME TO");
/* ALTER TRIGGER <name>, add ON */
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "TRIGGER") == 0)
+ else if (TAIL_MATCHES3("ALTER", "TRIGGER", ANY))
COMPLETE_WITH_CONST("ON");
- else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev3_wd, "TRIGGER") == 0)
+ else if (TAIL_MATCHES4("ALTER", "TRIGGER", ANY, ANY))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
@@ -1498,22 +1426,17 @@ psql_completion(const char *text, int start, int end)
/*
* If we have ALTER TRIGGER <sth> 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 (TAIL_MATCHES4("ALTER", "TRIGGER", ANY, "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* ALTER TRIGGER <name> ON <name> */
- else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev4_wd, "TRIGGER") == 0 &&
- pg_strcasecmp(prev2_wd, "ON") == 0)
+ else if (TAIL_MATCHES5("ALTER", "TRIGGER", ANY, "ON", ANY))
COMPLETE_WITH_CONST("RENAME TO");
/*
* If we detect ALTER TABLE <name>, suggest sub commands
*/
- else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "TABLE") == 0)
+ else if (TAIL_MATCHES3("ALTER", "TABLE", ANY))
{
static const char *const list_ALTER2[] =
{"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
@@ -1523,279 +1446,135 @@ 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)
- {
- 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))
- {
- 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 (TAIL_MATCHES4("ALTER", "TABLE", ANY, "ENABLE"))
+ COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
+ "TRIGGER");
+ else if (TAIL_MATCHES4("TABLE", ANY, "ENABLE", "REPLICA|ALWAYS"))
+ COMPLETE_WITH_LIST2("RULE", "TRIGGER");
+ else if (TAIL_MATCHES5("ALTER", "TABLE", ANY, "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 (TAIL_MATCHES6("ALTER", "TABLE", ANY, "ENABLE", ANY, "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 (TAIL_MATCHES5("ALTER", "TABLE", ANY, "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 (TAIL_MATCHES6("ALTER", "TABLE", ANY, "ENABLE", ANY, "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 (TAIL_MATCHES4("ALTER", "TABLE", ANY, "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 (TAIL_MATCHES5("ALTER", "TABLE", ANY, "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 (TAIL_MATCHES4("ALTER", "TABLE", ANY, "DISABLE"))
+ COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
+ else if (TAIL_MATCHES5("ALTER", "TABLE", ANY, "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 (TAIL_MATCHES5("ALTER", "TABLE", ANY, "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 (TAIL_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 (TAIL_MATCHES4("ALTER", "TABLE", ANY, "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 (TAIL_MATCHES4("ALTER", "TABLE", ANY, "RENAME"))
COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
/*
* If we have TABLE <sth> 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 (TAIL_MATCHES4("TABLE", ANY, "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 (TAIL_MATCHES5("ALTER", "TABLE", ANY, "RENAME", ANY) &&
+ !TAIL_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 (TAIL_MATCHES6("ALTER", "TABLE", ANY, "RENAME", "COLUMN|CONSTRAINT", ANY) &&
+ !TAIL_MATCHES1("TO"))
COMPLETE_WITH_CONST("TO");
/* If we have TABLE <sth> 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 (TAIL_MATCHES3("TABLE", ANY, "DROP"))
+ COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
/* If we have ALTER TABLE <sth> 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 (TAIL_MATCHES5("ALTER", "TABLE", ANY, "DROP", "COLUMN"))
COMPLETE_WITH_ATTR(prev3_wd, "");
/*
* If we have ALTER TABLE <sth> 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 (TAIL_MATCHES5("ALTER", "TABLE", ANY, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
}
/* ALTER TABLE ALTER [COLUMN] <foo> */
- 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 (TAIL_MATCHES3("ALTER", "COLUMN", ANY) ||
+ TAIL_MATCHES4("TABLE", ANY, "ALTER", ANY))
+ COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
/* ALTER TABLE ALTER [COLUMN] <foo> 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 (TAIL_MATCHES4("ALTER", "COLUMN", ANY, "SET") ||
+ TAIL_MATCHES5("TABLE", ANY, "ALTER", ANY, "SET"))
+ COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
/* ALTER TABLE ALTER [COLUMN] <foo> 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 (TAIL_MATCHES5("ALTER", "COLUMN", ANY, "SET", "(") ||
+ TAIL_MATCHES4("ALTER", ANY, "SET", "("))
+ COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
/* ALTER TABLE ALTER [COLUMN] <foo> 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 (TAIL_MATCHES5("ALTER", "COLUMN", ANY, "SET", "STORAGE") ||
+ TAIL_MATCHES4("ALTER", ANY, "SET", "STORAGE"))
+ COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
/* ALTER TABLE ALTER [COLUMN] <foo> 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 (TAIL_MATCHES4("ALTER", "COLUMN", ANY, "DROP") ||
+ TAIL_MATCHES5("TABLE", ANY, "ALTER", ANY, "DROP"))
+ COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
+ else if (TAIL_MATCHES3("TABLE", ANY, "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 (TAIL_MATCHES4("TABLE", ANY, "CLUSTER", "ON"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_index_of_table);
}
/* If we have TABLE <sth> 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 (TAIL_MATCHES3("TABLE", ANY, "SET"))
+ COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT");
/* If we have TABLE <sth> 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 (TAIL_MATCHES4("TABLE", ANY, "SET", "TABLESPACE"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
/* If we have TABLE <sth> 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 (TAIL_MATCHES4("TABLE", ANY, "SET", "WITHOUT"))
+ COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
/* ALTER TABLE <foo> RESET */
- else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
- pg_strcasecmp(prev_wd, "RESET") == 0)
+ else if (TAIL_MATCHES3("TABLE", ANY, "RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER TABLE <foo> 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 (TAIL_MATCHES4("TABLE", ANY, "SET|RESET", "("))
{
static const char *const list_TABLEOPTIONS[] =
{
@@ -1832,246 +1611,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 (TAIL_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 (TAIL_MATCHES5("TABLE", ANY, "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 (TAIL_MATCHES4("TABLE", ANY, "REPLICA", "IDENTITY"))
+ COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
+ else if (TAIL_MATCHES3("TABLE", ANY, "REPLICA"))
COMPLETE_WITH_CONST("IDENTITY");
- }
/* ALTER TABLESPACE <foo> 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 (TAIL_MATCHES3("ALTER", "TABLESPACE", ANY))
+ COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
/* ALTER TABLESPACE <foo> 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 (TAIL_MATCHES4("ALTER", "TABLESPACE", ANY, "SET|RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER TABLESPACE <foo> 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 (TAIL_MATCHES5("ALTER", "TABLESPACE", ANY, "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 (TAIL_MATCHES3("ALTER", "TEXT", "SEARCH"))
+ COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
+ else if (TAIL_MATCHES5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", ANY))
+ COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
+ else if (TAIL_MATCHES5("ALTER", "TEXT", "SEARCH", "DICTIONARY", ANY))
+ COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
+ else if (TAIL_MATCHES5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", ANY))
+ COMPLETE_WITH_LIST6("ADD MAPPING FOR", "ALTER MAPPING", "DROP MAPPING FOR",
+ "OWNER TO", "RENAME TO", "SET SCHEMA");
/* complete ALTER TYPE <foo> 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 (TAIL_MATCHES3("ALTER", "TYPE", ANY))
+ COMPLETE_WITH_LIST7("ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE",
+ "DROP ATTRIBUTE", "OWNER TO", "RENAME", "SET SCHEMA");
/* complete ALTER TYPE <foo> 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 (TAIL_MATCHES4("ALTER", "TYPE", ANY, "ADD"))
+ COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
/* ALTER TYPE <foo> 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 (TAIL_MATCHES4("ALTER", "TYPE", ANY, "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 (TAIL_MATCHES5("TYPE", ANY, "RENAME", "ATTRIBUTE", ANY))
COMPLETE_WITH_CONST("TO");
/*
* If we have TYPE <sth> 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 (TAIL_MATCHES4("TYPE", ANY, "ALTER|DROP|RENAME", "ATTRIBUTE"))
COMPLETE_WITH_ATTR(prev3_wd, "");
/* ALTER TYPE ALTER ATTRIBUTE <foo> */
- else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
- pg_strcasecmp(prev2_wd, "ATTRIBUTE") == 0))
- {
+ else if (TAIL_MATCHES3("ALTER", "ATTRIBUTE", ANY))
COMPLETE_WITH_CONST("TYPE");
- }
/* complete ALTER GROUP <foo> */
- 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 (TAIL_MATCHES3("ALTER", "GROUP", ANY))
+ COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
/* complete ALTER GROUP <foo> 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 (TAIL_MATCHES4("ALTER", "GROUP", ANY, "ADD|DROP"))
COMPLETE_WITH_CONST("USER");
/* complete {ALTER} GROUP <foo> 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 (TAIL_MATCHES4("GROUP", ANY, "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 (TAIL_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 (TAIL_MATCHES1("COMMIT"))
+ COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
/* RELEASE SAVEPOINT */
- else if (pg_strcasecmp(prev_wd, "RELEASE") == 0)
+ else if (TAIL_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 (TAIL_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 (TAIL_MATCHES1("CLUSTER") && !TAIL_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 (TAIL_MATCHES2("CLUSTER", "VERBOSE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
/* If we have CLUSTER <sth>, 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 (TAIL_MATCHES2("CLUSTER", ANY) && !TAIL_MATCHES1("VERBOSE"))
COMPLETE_WITH_CONST("USING");
- }
/* If we have CLUSTER VERBOSE <sth>, then add "USING" */
- else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 &&
- pg_strcasecmp(prev2_wd, "VERBOSE") == 0)
- {
+ else if (TAIL_MATCHES3("CLUSTER", "VERBOSE", ANY))
COMPLETE_WITH_CONST("USING");
- }
/*
* If we have CLUSTER <sth> USING, then add the index as well.
*/
- else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 &&
- pg_strcasecmp(prev_wd, "USING") == 0)
+ else if (TAIL_MATCHES3("CLUSTER", ANY, "USING"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_index_of_table);
@@ -2080,19 +1722,16 @@ psql_completion(const char *text, int start, int end)
/*
* If we have CLUSTER VERBOSE <sth> 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 (TAIL_MATCHES4("CLUSTER", "VERBOSE", ANY, "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 (TAIL_MATCHES1("COMMENT"))
COMPLETE_WITH_CONST("ON");
- else if (pg_strcasecmp(prev2_wd, "COMMENT") == 0 &&
- pg_strcasecmp(prev_wd, "ON") == 0)
+ else if (TAIL_MATCHES2("COMMENT", "ON"))
{
static const char *const list_COMMENT[] =
{"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION",
@@ -2104,66 +1743,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 (TAIL_MATCHES3("COMMENT", "ON", "FOREIGN"))
+ COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
+ else if (TAIL_MATCHES4("COMMENT", "ON", "TEXT", "SEARCH"))
+ COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
+ else if (TAIL_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 (TAIL_MATCHES4("COMMENT", "ON", "CONSTRAINT", ANY))
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 (TAIL_MATCHES5("COMMENT", "ON", "CONSTRAINT", ANY, "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 (TAIL_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 (TAIL_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 ((TAIL_MATCHES4("COMMENT", "ON", ANY, ANY) ||
+ TAIL_MATCHES5("COMMENT", "ON", ANY, ANY, ANY) ||
+ TAIL_MATCHES6("COMMENT", "ON", ANY, ANY, ANY, ANY)) &&
+ !TAIL_MATCHES1("IS"))
COMPLETE_WITH_CONST("IS");
/* COPY */
@@ -2172,59 +1772,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 (TAIL_MATCHES1("COPY|\\copy") || TAIL_MATCHES2("COPY", "BINARY"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* If we have COPY|BINARY <sth>, 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 (TAIL_MATCHES2("COPY|\\copy|BINARY", ANY))
+ COMPLETE_WITH_LIST2("FROM", "TO");
/* If we have COPY|BINARY <sth> 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 (TAIL_MATCHES3("COPY|\\copy|BINARY", ANY, "FROM|TO"))
{
completion_charp = "";
matches = completion_matches(text, complete_from_files);
}
/* Handle COPY|BINARY <sth> 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 (TAIL_MATCHES4("COPY|\\copy|BINARY", ANY, "FROM|TO", ANY))
+ COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV", "ENCODING");
/* Handle COPY|BINARY <sth> 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 (TAIL_MATCHES3("FROM|TO", ANY, "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 (TAIL_MATCHES3("CREATE", "DATABASE", ANY))
{
static const char *const list_DATABASE[] =
{"OWNER", "TEMPLATE", "ENCODING", "TABLESPACE", "IS_TEMPLATE",
@@ -2234,403 +1803,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 (TAIL_MATCHES4("CREATE", "DATABASE", ANY, "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 (TAIL_MATCHES2("CREATE", "EXTENSION"))
COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
/* CREATE EXTENSION <name> */
- else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev2_wd, "EXTENSION") == 0)
+ else if (TAIL_MATCHES3("CREATE", "EXTENSION", ANY))
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 (TAIL_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 (TAIL_MATCHES5("CREATE", "FOREIGN", "DATA", "WRAPPER", ANY))
+ 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 (TAIL_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 (TAIL_MATCHES2("CREATE|UNIQUE", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
" UNION SELECT 'ON'"
" UNION SELECT 'CONCURRENTLY'");
/* Complete ... INDEX [<name>] 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 (TAIL_MATCHES3("INDEX", ANY, "ON") ||
+ TAIL_MATCHES2("INDEX|CONCURRENTLY", "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
/* If we have CREATE|UNIQUE INDEX <sth> 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 (TAIL_MATCHES3("INDEX", ANY, "CONCURRENTLY") ||
+ TAIL_MATCHES2("INDEX", "CONCURRENTLY"))
COMPLETE_WITH_CONST("ON");
/* If we have CREATE|UNIQUE INDEX <sth>, 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 (TAIL_MATCHES3("CREATE|UNIQUE", "INDEX", ANY))
+ COMPLETE_WITH_LIST2("CONCURRENTLY", "ON");
/*
* Complete INDEX <name> ON <table> 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 (TAIL_MATCHES4("INDEX", ANY, "ON", ANY) ||
+ TAIL_MATCHES3("INDEX|CONCURRENTLY", "ON", ANY))
+ COMPLETE_WITH_LIST2("(", "USING");
+ else if (TAIL_MATCHES5("INDEX", ANY, "ON", ANY, "(") ||
+ TAIL_MATCHES4("INDEX|CONCURRENTLY", "ON", ANY, "("))
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 (TAIL_MATCHES5("ON", ANY, "USING", ANY, "("))
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 (TAIL_MATCHES6("INDEX", ANY, ANY, "ON", ANY, "USING") ||
+ TAIL_MATCHES5("INDEX", ANY, "ON", ANY, "USING") ||
+ TAIL_MATCHES4("INDEX", "ON", ANY, "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 (TAIL_MATCHES4("ON", ANY, "USING", ANY) &&
+ !TAIL_MATCHES6("POLICY", ANY, ANY, ANY, ANY, ANY) &&
+ !TAIL_MATCHES4("FOR", ANY, ANY, ANY))
COMPLETE_WITH_CONST("(");
/* CREATE POLICY */
/* Complete "CREATE POLICY <name> ON" */
- else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev2_wd, "POLICY") == 0)
+ else if (TAIL_MATCHES3("CREATE", "POLICY", ANY))
COMPLETE_WITH_CONST("ON");
/* Complete "CREATE POLICY <name> ON <table>" */
- else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev3_wd, "POLICY") == 0 &&
- pg_strcasecmp(prev_wd, "ON") == 0)
+ else if (TAIL_MATCHES4("CREATE", "POLICY", ANY, "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* Complete "CREATE POLICY <name> ON <table> 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 (TAIL_MATCHES5("CREATE", "POLICY", ANY, "ON", ANY))
+ COMPLETE_WITH_LIST4("FOR", "TO", "USING", "WITH CHECK");
/*
* Complete "CREATE POLICY <name> ON <table> 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 (TAIL_MATCHES6("CREATE", "POLICY", ANY, "ON", ANY, "FOR"))
+ COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
/* Complete "CREATE POLICY <name> ON <table> 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 (TAIL_MATCHES6("POLICY", ANY, "ON", ANY, "FOR", "INSERT"))
+ COMPLETE_WITH_LIST2("TO", "WITH CHECK");
/*
* Complete "CREATE POLICY <name> ON <table> FOR SELECT TO|USING" Complete
* "CREATE POLICY <name> ON <table> 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 (TAIL_MATCHES6("POLICY", ANY, "ON", ANY, "FOR", "SELECT|DELETE"))
+ COMPLETE_WITH_LIST2("TO", "USING");
/*
* Complete "CREATE POLICY <name> ON <table> FOR ALL TO|USING|WITH CHECK"
* Complete "CREATE POLICY <name> ON <table> 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 (TAIL_MATCHES6("POLICY", ANY, "ON", ANY, "FOR", "ALL|UPDATE"))
+ COMPLETE_WITH_LIST3("TO", "USING", "WITH CHECK");
/* Complete "CREATE POLICY <name> ON <table> TO <role>" */
- 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 (TAIL_MATCHES6("CREATE", "POLICY", ANY, "ON", ANY, "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
/* Complete "CREATE POLICY <name> ON <table> 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 (TAIL_MATCHES6("CREATE", "POLICY", ANY, "ON", ANY, "USING"))
COMPLETE_WITH_CONST("(");
/* CREATE RULE */
/* Complete "CREATE RULE <sth>" with "AS" */
- else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev2_wd, "RULE") == 0)
+ else if (TAIL_MATCHES3("CREATE", "RULE", ANY))
COMPLETE_WITH_CONST("AS");
/* Complete "CREATE RULE <sth> 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 (TAIL_MATCHES4("CREATE", "RULE", ANY, "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 (TAIL_MATCHES4("RULE", ANY, "AS", "ON"))
+ COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
/* Complete "AS ON <sth with a 'T' :)>" 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 (TAIL_MATCHES3("AS", "ON", "SELECT|UPDATE|DELETE|INSERT"))
COMPLETE_WITH_CONST("TO");
/* Complete "AS ON <sth> 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 (TAIL_MATCHES4("AS", "ON", "SELECT|UPDATE|DELETE|INSERT", "TO"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* CREATE TEMP/TEMPORARY SEQUENCE <name> */
- 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 (TAIL_MATCHES3("CREATE", "SEQUENCE", ANY) ||
+ TAIL_MATCHES4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", ANY))
+ COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
+ "CYCLE", "OWNED BY", "START WITH");
/* CREATE TEMP/TEMPORARY SEQUENCE <name> 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 (TAIL_MATCHES4("CREATE", "SEQUENCE", ANY, "NO") ||
+ TAIL_MATCHES5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", ANY, "NO"))
+ COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
/* CREATE SERVER <name> */
- 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 (TAIL_MATCHES3("CREATE", "SERVER", ANY))
+ 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 (TAIL_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 (TAIL_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 (TAIL_MATCHES3("CREATE", "TABLESPACE", ANY))
+ 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 (TAIL_MATCHES5("CREATE", "TABLESPACE", ANY, "OWNER", ANY))
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 (TAIL_MATCHES3("CREATE", "TEXT", "SEARCH"))
+ COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
+ else if (TAIL_MATCHES4("TEXT", "SEARCH", "CONFIGURATION", ANY))
COMPLETE_WITH_CONST("(");
/* CREATE TRIGGER */
/* complete CREATE TRIGGER <name> 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 (TAIL_MATCHES3("CREATE", "TRIGGER", ANY))
+ COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
/* complete CREATE TRIGGER <name> 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 (TAIL_MATCHES4("CREATE", "TRIGGER", ANY, "BEFORE|AFTER"))
+ COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
/* complete CREATE TRIGGER <name> 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 (TAIL_MATCHES5("CREATE", "TRIGGER", ANY, "INSTEAD", "OF"))
+ COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
/* complete CREATE TRIGGER <name> 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 (TAIL_MATCHES5("CREATE", "TRIGGER", ANY, "BEFORE|AFTER", ANY) ||
+ TAIL_MATCHES6("CREATE", "TRIGGER", ANY, "INSTEAD", "OF", ANY))
+ COMPLETE_WITH_LIST2("ON", "OR");
/*
* complete CREATE TRIGGER <name> 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 (TAIL_MATCHES5("TRIGGER", ANY, "BEFORE|AFTER", ANY, "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 (TAIL_MATCHES4("INSTEAD", "OF", ANY, "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 (TAIL_MATCHES1("EXECUTE") && !TAIL_MATCHES3("", "|GRANT", "EXECUTE"))
COMPLETE_WITH_CONST("PROCEDURE");
/* CREATE ROLE,USER,GROUP <name> */
- 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 (TAIL_MATCHES3("CREATE", "ROLE|GROUP|USER", ANY) &&
+ !TAIL_MATCHES3("CREATE", "USER", "MAPPING"))
{
static const char *const list_CREATEROLE[] =
{"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
@@ -2644,11 +2004,7 @@ psql_completion(const char *text, int start, int end)
}
/* CREATE ROLE,USER,GROUP <name> 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 (TAIL_MATCHES4("CREATE", "ROLE|GROUP|USER", ANY, "WITH"))
{
/* Similar to the above, but don't complete "WITH" again. */
static const char *const list_CREATEROLE_WITH[] =
@@ -2666,91 +2022,47 @@ psql_completion(const char *text, int start, int end)
* complete CREATE ROLE,USER,GROUP <name> 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 (TAIL_MATCHES4("CREATE", "ROLE|USER|GROUP", ANY, "ENCRYPTED|UNENCRYPTED"))
COMPLETE_WITH_CONST("PASSWORD");
- }
/* complete CREATE ROLE,USER,GROUP <name> 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 (TAIL_MATCHES4("CREATE", "ROLE|USER|GROUP", ANY, "IN"))
+ COMPLETE_WITH_LIST2("GROUP", "ROLE");
/* CREATE VIEW */
/* Complete CREATE VIEW <name> with AS */
- else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev2_wd, "VIEW") == 0)
+ else if (TAIL_MATCHES3("CREATE", "VIEW", ANY))
COMPLETE_WITH_CONST("AS");
/* Complete "CREATE VIEW <sth> 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 (TAIL_MATCHES4("CREATE", "VIEW", ANY, "AS"))
COMPLETE_WITH_CONST("SELECT");
/* CREATE MATERIALIZED VIEW */
- else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev_wd, "MATERIALIZED") == 0)
+ else if (TAIL_MATCHES2("CREATE", "MATERIALIZED"))
COMPLETE_WITH_CONST("VIEW");
/* Complete CREATE MATERIALIZED VIEW <name> with AS */
- else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 &&
- pg_strcasecmp(prev2_wd, "VIEW") == 0)
+ else if (TAIL_MATCHES3("CREATE", "MATERIALIZED", "VIEW"))
COMPLETE_WITH_CONST("AS");
/* Complete "CREATE MATERIALIZED VIEW <sth> 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 (TAIL_MATCHES5("CREATE", "MATERIALIZED", "VIEW", ANY, "AS"))
COMPLETE_WITH_CONST("SELECT");
/* CREATE EVENT TRIGGER */
- else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev_wd, "EVENT") == 0)
+ else if (TAIL_MATCHES2("CREATE", "EVENT"))
COMPLETE_WITH_CONST("TRIGGER");
/* Complete CREATE EVENT TRIGGER <name> with ON */
- else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
- pg_strcasecmp(prev3_wd, "EVENT") == 0 &&
- pg_strcasecmp(prev2_wd, "TRIGGER") == 0)
+ else if (TAIL_MATCHES4("CREATE", "EVENT", "TRIGGER", ANY))
COMPLETE_WITH_CONST("ON");
/* Complete CREATE EVENT TRIGGER <name> 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 (TAIL_MATCHES5("CREATE", "EVENT", "TRIGGER", ANY, "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 (TAIL_MATCHES2("DECLARE", ANY))
+ 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 (TAIL_MATCHES1("CURSOR"))
+ COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
/* DELETE */
@@ -2758,231 +2070,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 (TAIL_MATCHES1("DELETE") && !TAIL_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 (TAIL_MATCHES2("DELETE", "FROM"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
/* Complete DELETE FROM <table> */
- 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 (TAIL_MATCHES3("DELETE", "FROM", ANY))
+ 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 (TAIL_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 (TAIL_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 (TAIL_MATCHES3("DROP", "AGGREGATE", ANY))
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 (TAIL_MATCHES3("DROP",
+ "COLLATION|CONVERSION|DOMAIN|EXTENSION|FUNCTION|INDEX|LANGUAGE|SCHEMA|SEQUENCES|SERVER|TABLE|TYPE|VIEW",
+ ANY) ||
+ (TAIL_MATCHES4("DROP", "AGGREGATE", ANY, ANY) && ends_with(prev_wd, ')')) ||
+ TAIL_MATCHES4("DROP", "EVENT", "TRIGGER", ANY) ||
+ TAIL_MATCHES5("DROP", "FOREIGN", "DATA", "WRAPPER", ANY) ||
+ TAIL_MATCHES5("DROP", "TEXT", "SEARCH", "CONFIGURATION|DICTIONARY|PARSER|TEMPLATE", ANY))
+ {
+ if (TAIL_MATCHES3("DROP", "FUNCTION", ANY))
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 (TAIL_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 (TAIL_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 (TAIL_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 (TAIL_MATCHES4("DROP", "AGGREGATE|FUNCTION", ANY, "("))
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 (TAIL_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 (TAIL_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 (TAIL_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 (TAIL_MATCHES3("DROP", "TRIGGER", ANY))
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 (TAIL_MATCHES4("DROP", "TRIGGER", ANY, "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 (TAIL_MATCHES5("DROP", "TRIGGER", ANY, "ON", ANY))
+ COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
/* DROP EVENT TRIGGER */
- else if (pg_strcasecmp(prev2_wd, "DROP") == 0 &&
- pg_strcasecmp(prev_wd, "EVENT") == 0)
- {
+ else if (TAIL_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 (TAIL_MATCHES3("DROP", "EVENT", "TRIGGER"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
- }
/* DROP POLICY <name> */
- else if (pg_strcasecmp(prev2_wd, "DROP") == 0 &&
- pg_strcasecmp(prev_wd, "POLICY") == 0)
- {
+ else if (TAIL_MATCHES2("DROP", "POLICY"))
COMPLETE_WITH_QUERY(Query_for_list_of_policies);
- }
/* DROP POLICY <name> ON */
- else if (pg_strcasecmp(prev3_wd, "DROP") == 0 &&
- pg_strcasecmp(prev2_wd, "POLICY") == 0)
- {
+ else if (TAIL_MATCHES3("DROP", "POLICY", ANY))
COMPLETE_WITH_CONST("ON");
- }
/* DROP POLICY <name> ON <table> */
- else if (pg_strcasecmp(prev4_wd, "DROP") == 0 &&
- pg_strcasecmp(prev3_wd, "POLICY") == 0 &&
- pg_strcasecmp(prev_wd, "ON") == 0)
+ else if (TAIL_MATCHES4("DROP", "POLICY", ANY, "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 (TAIL_MATCHES3("DROP", "RULE", ANY))
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 (TAIL_MATCHES4("DROP", "RULE", ANY, "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 (TAIL_MATCHES5("DROP", "RULE", ANY, "ON", ANY))
+ 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 (MATCHES1("EXECUTE"))
COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
/* EXPLAIN */
@@ -2990,85 +2180,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 (TAIL_MATCHES1("EXPLAIN"))
+ COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
+ "ANALYZE", "VERBOSE");
+ else if (TAIL_MATCHES2("EXPLAIN", "ANALYZE|ANALYSE"))
+ COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "VERBOSE");
+ else if (TAIL_MATCHES2("EXPLAIN", "VERBOSE") ||
+ TAIL_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 (TAIL_MATCHES1("FETCH|MOVE"))
+ COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
/* Complete FETCH <sth> 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 (TAIL_MATCHES2("FETCH|MOVE", ANY))
+ COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
/*
* Complete FETCH <sth1> <sth2> 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 (TAIL_MATCHES3("FETCH|MOVE", ANY, ANY))
+ 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 (TAIL_MATCHES3("FOREIGN", "DATA", "WRAPPER") &&
+ !TAIL_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 (TAIL_MATCHES2("FOREIGN", "TABLE") &&
+ !TAIL_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 (TAIL_MATCHES1("GRANT|REVOKE"))
{
COMPLETE_WITH_QUERY(Query_for_list_of_roles
" UNION SELECT 'SELECT'"
@@ -3090,27 +2240,13 @@ psql_completion(const char *text, int start, int end)
* Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
* TO/FROM
*/
- else if (pg_strcasecmp(prev2_wd, "GRANT") == 0 ||
- pg_strcasecmp(prev2_wd, "REVOKE") == 0)
+ else if (TAIL_MATCHES2("GRANT|REVOKE", ANY))
{
- 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 (TAIL_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 (TAIL_MATCHES2("GRANT", ANY))
COMPLETE_WITH_CONST("TO");
else
COMPLETE_WITH_CONST("FROM");
@@ -3128,9 +2264,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 (TAIL_MATCHES3("GRANT|REVOKE", ANY, "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
" UNION SELECT 'DATABASE'"
" UNION SELECT 'DOMAIN'"
@@ -3142,195 +2276,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 (TAIL_MATCHES4("GRANT|REVOKE", ANY, "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 (TAIL_MATCHES4("GRANT|REVOKE", ANY, "ON", ANY))
{
- if (pg_strcasecmp(prev_wd, "DATABASE") == 0)
+ if (TAIL_MATCHES1("DATABASE"))
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
- else if (pg_strcasecmp(prev_wd, "DOMAIN") == 0)
+ else if (TAIL_MATCHES1("DOMAIN"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
- else if (pg_strcasecmp(prev_wd, "FUNCTION") == 0)
+ else if (TAIL_MATCHES1("FUNCTION"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
- else if (pg_strcasecmp(prev_wd, "LANGUAGE") == 0)
+ else if (TAIL_MATCHES1("LANGUAGE"))
COMPLETE_WITH_QUERY(Query_for_list_of_languages);
- else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0)
+ else if (TAIL_MATCHES1("SCHEMA"))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
- else if (pg_strcasecmp(prev_wd, "TABLESPACE") == 0)
+ else if (TAIL_MATCHES1("TABLESPACE"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
- else if (pg_strcasecmp(prev_wd, "TYPE") == 0)
+ else if (TAIL_MATCHES1("TYPE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
- else if (pg_strcasecmp(prev4_wd, "GRANT") == 0)
+ else if (TAIL_MATCHES4("GRANT", ANY, ANY, ANY))
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 (TAIL_MATCHES5("GRANT", ANY, "ON", ANY, ANY))
{
- if (pg_strcasecmp(prev_wd, "TO") == 0)
+ if (TAIL_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 (TAIL_MATCHES5("REVOKE", ANY, "ON", ANY, ANY))
{
- if (pg_strcasecmp(prev_wd, "FROM") == 0)
+ if (TAIL_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 (TAIL_MATCHES3("GRANT", ANY, "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 (TAIL_MATCHES3("REVOKE", ANY, "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 (TAIL_MATCHES3("FROM", ANY, "GROUP"))
COMPLETE_WITH_CONST("BY");
/* IMPORT FOREIGN SCHEMA */
- else if (pg_strcasecmp(prev_wd, "IMPORT") == 0)
+ else if (TAIL_MATCHES1("IMPORT"))
COMPLETE_WITH_CONST("FOREIGN SCHEMA");
- else if (pg_strcasecmp(prev2_wd, "IMPORT") == 0 &&
- pg_strcasecmp(prev_wd, "FOREIGN") == 0)
+ else if (TAIL_MATCHES2("IMPORT", "FOREIGN"))
COMPLETE_WITH_CONST("SCHEMA");
/* INSERT */
/* Complete INSERT with "INTO" */
- else if (pg_strcasecmp(prev_wd, "INSERT") == 0)
+ else if (TAIL_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 (TAIL_MATCHES2("INSERT", "INTO"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
/* Complete "INSERT INTO <table> (" with attribute names */
- else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 &&
- pg_strcasecmp(prev3_wd, "INTO") == 0 &&
- pg_strcasecmp(prev_wd, "(") == 0)
+ else if (TAIL_MATCHES4("INSERT", "INTO", ANY, "("))
COMPLETE_WITH_ATTR(prev2_wd, "");
/*
* Complete INSERT INTO <table> 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 (TAIL_MATCHES3("INSERT", "INTO", ANY))
+ COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
/*
* Complete INSERT INTO <table> (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 (TAIL_MATCHES4("INSERT", "INTO", ANY, ANY) && 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 (TAIL_MATCHES1("VALUES") && !TAIL_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 (TAIL_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 (TAIL_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] <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 ((TAIL_MATCHES2("LOCK", ANY) && !TAIL_MATCHES2("LOCK", "TABLE")) ||
+ TAIL_MATCHES3("LOCK", "TABLE", ANY))
COMPLETE_WITH_CONST("IN");
/* Complete LOCK [TABLE] <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 (TAIL_MATCHES3("LOCK", ANY, "IN") ||
+ TAIL_MATCHES4("LOCK", "TABLE", ANY, "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 (TAIL_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 (TAIL_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 (TAIL_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 (TAIL_MATCHES3("FROM", ANY, "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 (TAIL_MATCHES4("FROM", ANY, "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 (TAIL_MATCHES3("PREPARE", ANY, "AS"))
+ COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
/*
* PREPARE TRANSACTION is missing on purpose. It's intended for transaction
@@ -3338,116 +2415,62 @@ 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 (TAIL_MATCHES1("REASSIGN"))
COMPLETE_WITH_CONST("OWNED");
- else if (pg_strcasecmp(prev_wd, "OWNED") == 0 &&
- pg_strcasecmp(prev2_wd, "REASSIGN") == 0)
+ else if (TAIL_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 (TAIL_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 (TAIL_MATCHES4("REASSIGN", "OWNED", "BY", ANY))
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 (TAIL_MATCHES5("REASSIGN", "OWNED", "BY", ANY, "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
/* REFRESH MATERIALIZED VIEW */
- else if (pg_strcasecmp(prev_wd, "REFRESH") == 0)
+ else if (TAIL_MATCHES1("REFRESH"))
COMPLETE_WITH_CONST("MATERIALIZED VIEW");
- else if (pg_strcasecmp(prev2_wd, "REFRESH") == 0 &&
- pg_strcasecmp(prev_wd, "MATERIALIZED") == 0)
+ else if (TAIL_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 (TAIL_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 (TAIL_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 (TAIL_MATCHES4("REFRESH", "MATERIALIZED", "VIEW", ANY))
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 (TAIL_MATCHES5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", ANY))
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)
- {
- 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 (TAIL_MATCHES5("REFRESH", "MATERIALIZED", "VIEW", ANY, "WITH"))
+ COMPLETE_WITH_LIST2("NO DATA", "DATA");
+ else if (TAIL_MATCHES6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", ANY, "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 (TAIL_MATCHES6("REFRESH", "MATERIALIZED", "VIEW", ANY, "WITH", "NO"))
COMPLETE_WITH_CONST("DATA");
/* REINDEX */
- else if (pg_strcasecmp(prev_wd, "REINDEX") == 0)
- {
- 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 (TAIL_MATCHES1("REINDEX"))
+ COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
+ else if (TAIL_MATCHES2("REINDEX", ANY))
{
- if (pg_strcasecmp(prev_wd, "TABLE") == 0)
+ if (TAIL_MATCHES1("TABLE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
- else if (pg_strcasecmp(prev_wd, "INDEX") == 0)
+ else if (TAIL_MATCHES1("INDEX"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
- else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0)
+ else if (TAIL_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 (TAIL_MATCHES1("SYSTEM|DATABASE"))
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
}
/* SECURITY LABEL */
- else if (pg_strcasecmp(prev_wd, "SECURITY") == 0)
+ else if (TAIL_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 (TAIL_MATCHES2("SECURITY", "LABEL"))
+ COMPLETE_WITH_LIST2("ON", "FOR");
+ else if (TAIL_MATCHES4("SECURITY", "LABEL", "FOR", ANY))
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 (TAIL_MATCHES3("SECURITY", "LABEL", "ON") ||
+ TAIL_MATCHES5("SECURITY", "LABEL", "FOR", ANY, "ON"))
{
static const char *const list_SECURITY_LABEL[] =
{"LANGUAGE", "SCHEMA", "SEQUENCE", "TABLE", "TYPE", "VIEW",
@@ -3456,9 +2479,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 (TAIL_MATCHES5("SECURITY", "LABEL", "ON", ANY, ANY))
COMPLETE_WITH_CONST("IS");
/* SELECT */
@@ -3466,135 +2487,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 (TAIL_MATCHES1("SET|RESET") && !MATCHES3("UPDATE", ANY, "SET"))
COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
- else if (pg_strcasecmp(prev_wd, "SHOW") == 0)
+ else if (TAIL_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 (TAIL_MATCHES2("SET|BEGIN|START", "TRANSACTION") ||
+ TAIL_MATCHES2("BEGIN", "WORK") ||
+ TAIL_MATCHES4("SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
+ COMPLETE_WITH_LIST2("ISOLATION LEVEL", "READ");
+ else if (TAIL_MATCHES3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
+ TAIL_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 (TAIL_MATCHES4("SET|BEGIN|START|AS", "TRANSACTION|WORK", "ISOLATION", "LEVEL"))
+ COMPLETE_WITH_LIST3("READ", "REPEATABLE", "SERIALIZABLE");
+ else if (TAIL_MATCHES4("TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ"))
+ COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
+ else if (TAIL_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 (TAIL_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 (TAIL_MATCHES2("SET", "CONSTRAINTS"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
- }
/* Complete SET CONSTRAINTS <foo> 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 (TAIL_MATCHES3("SET", "CONSTRAINTS", ANY))
+ COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
/* Complete SET ROLE */
- else if (pg_strcasecmp(prev2_wd, "SET") == 0 &&
- pg_strcasecmp(prev_wd, "ROLE") == 0)
+ else if (TAIL_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 (TAIL_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 (TAIL_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 (TAIL_MATCHES2("RESET", "SESSION"))
COMPLETE_WITH_CONST("AUTHORIZATION");
/* Complete SET <var> 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 (MATCHES2("SET", ANY))
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 (TAIL_MATCHES3("SET", ANY, "TO|="))
{
- if (pg_strcasecmp(prev2_wd, "DateStyle") == 0)
+ if (TAIL_MATCHES2("DateStyle", "TO|="))
{
static const char *const my_list[] =
{"ISO", "SQL", "Postgres", "German",
@@ -3604,66 +2541,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 (TAIL_MATCHES2("IntervalStyle", "TO|="))
+ COMPLETE_WITH_LIST4("postgres", "postgres_verbose", "sql_standard", "iso_8601");
+ else if (TAIL_MATCHES2("GEQO", "TO|="))
+ COMPLETE_WITH_LIST3("ON", "OFF", "DEFAULT");
+ else if (TAIL_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 (TAIL_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 (TAIL_MATCHES2("", "TABLE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
/* TABLESAMPLE */
- else if (pg_strcasecmp(prev_wd, "TABLESAMPLE") == 0)
+ else if (TAIL_MATCHES1("TABLESAMPLE"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
- else if (pg_strcasecmp(prev2_wd, "TABLESAMPLE") == 0)
+ else if (TAIL_MATCHES2("TABLESTAMPLE", ANY))
COMPLETE_WITH_CONST("(");
/* TRUNCATE */
- else if (pg_strcasecmp(prev_wd, "TRUNCATE") == 0)
+ else if (TAIL_MATCHES1("TRUNCATE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* UNLISTEN */
- else if (pg_strcasecmp(prev_wd, "UNLISTEN") == 0)
+ else if (TAIL_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 (TAIL_MATCHES1("UPDATE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
/* Complete UPDATE <table> with "SET" */
- else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0)
+ else if (TAIL_MATCHES2("UPDATE", ANY))
COMPLETE_WITH_CONST("SET");
/*
@@ -3671,83 +2590,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 (TAIL_MATCHES2(ANY, "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 (TAIL_MATCHES4("UPDATE", ANY, "SET", ANY))
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 (TAIL_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 (TAIL_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 (TAIL_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 (TAIL_MATCHES5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", ANY))
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 (TAIL_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 (TAIL_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 (TAIL_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 (TAIL_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 TAIL_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 (TAIL_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 (TAIL_MATCHES2("VERBOSE", "ANALYZE|ANALYSE") ||
+ TAIL_MATCHES2("ANALYZE|ANALYSE", "VERBOSE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
/* WITH [RECURSIVE] */
@@ -3756,29 +2646,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 (MATCHES1("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 (TAIL_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 (TAIL_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 (TAIL_MATCHES1("FROM") && !MATCHES3("COPY|\\copy", ANY, "FROM"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
/* ... JOIN ... */
- else if (pg_strcasecmp(prev_wd, "JOIN") == 0)
+ else if (TAIL_MATCHES1("JOIN"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
/* Backslash commands */
Thomas Munro wrote:
Thanks, good point. Here's a version that uses NULL via a macro ANY.
Aside from a few corrections it also now distinguishes between
TAIL_MATCHESn (common) and MATCHESn (rarely used for now), for example:
This looks pretty neat -- 100x neater than what we have, at any rate. I
would use your new MATCHESn() macros a bit more -- for instance the
completion for "ALTER but not ALTER after ALTER TABLE" could be
rephrased as simply MATCHES1("ALTER"), i.e. have it match at start of
command only. Maybe that's just a matter of going over the new code
after the initial run, so that we can have a first patch that's mostly
mechanical and a second pass in which more semantically relevant changes
are applied. Seems easier to review ...
I would use "ANY" as a keyword here. Sounds way too generic to me.
Maybe "CompleteAny" or something like that.
Stylistically, I find there's too much uppercasing here. Maybe rename the
macros like this instead:
+ else if (TailMatches4("ALL", "IN", "TABLESPACE", ANY)) + CompleteWithList2("SET TABLESPACE", "OWNED BY");
Not totally sure about this part TBH.
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Tue, Sep 8, 2015 at 1:56 AM, Alvaro Herrera <alvherre@2ndquadrant.com>
wrote:
Thomas Munro wrote:
Thanks, good point. Here's a version that uses NULL via a macro ANY.
Aside from a few corrections it also now distinguishes between
TAIL_MATCHESn (common) and MATCHESn (rarely used for now), for example:This looks pretty neat -- 100x neater than what we have, at any rate. I
would use your new MATCHESn() macros a bit more -- for instance the
completion for "ALTER but not ALTER after ALTER TABLE" could be
rephrased as simply MATCHES1("ALTER"), i.e. have it match at start of
command only. Maybe that's just a matter of going over the new code
after the initial run, so that we can have a first patch that's mostly
mechanical and a second pass in which more semantically relevant changes
are applied. Seems easier to review ...
+1
I would use "ANY" as a keyword here. Sounds way too generic to me.
Maybe "CompleteAny" or something like that.
MatchAny would make more sense to me.
Stylistically, I find there's too much uppercasing here. Maybe rename the
macros like this instead:
+ else if (TailMatches4("ALL", "IN", "TABLESPACE", ANY)) + CompleteWithList2("SET TABLESPACE", "OWNED BY");Not totally sure about this part TBH.
Ok, here's a rebased version that uses the style you suggested. It also
adds HeadMatchesN macros, so we can do this:
* Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
* CURRENT_USER, or SESSION_USER.
*/
- else if (((pg_strcasecmp(prev9_wd, "GRANT") == 0 ||
- pg_strcasecmp(prev8_wd, "GRANT") == 0 ||
- pg_strcasecmp(prev7_wd, "GRANT") == 0 ||
- pg_strcasecmp(prev6_wd, "GRANT") == 0 ||
- pg_strcasecmp(prev5_wd, "GRANT") == 0) &&
- pg_strcasecmp(prev_wd, "TO") == 0) ||
- ((pg_strcasecmp(prev9_wd, "REVOKE") == 0 ||
- pg_strcasecmp(prev8_wd, "REVOKE") == 0 ||
- pg_strcasecmp(prev7_wd, "REVOKE") == 0 ||
- pg_strcasecmp(prev6_wd, "REVOKE") == 0 ||
- pg_strcasecmp(prev5_wd, "REVOKE") == 0) &&
- pg_strcasecmp(prev_wd, "FROM") == 0))
+ else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
+ (HeadMatches1("REVOKE") && TailMatches1("FROM")))
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
So to recap:
MatchesN(...) -- matches the whole expression (up to lookback buffer size)
HeadMatchesN(...) -- matches the start of the expression (ditto)
TailMatchesN(...) -- matches the end of the expression
MatchAny -- placeholder
It would be nice to get rid of those numbers in the macro names, and I
understand that we can't use variadic macros. Should we use varargs
functions instead of macros? Then we could lose the numbers, but we'd need
to introduce global variables to keep the notation short and sweet (or pass
in the previous_words and previous_words_count, which would be ugly
boilerplate worse than the numbers).
--
Thomas Munro
http://www.enterprisedb.com
Attachments:
Attachments:
On Sun, Oct 18, 2015 at 5:31 PM, Thomas Munro <thomas.munro@enterprisedb.com
wrote:
Hi
Here is a new version merging recent changes.
For reasons I do not understand, "SET work_mem " does not complete with
"TO".
But if I change:
else if (Matches2("SET", MatchAny))
to:
else if (TailMatches2("SET", MatchAny))
Then it does.
Cheers,
Jeff
On Mon, Oct 19, 2015 at 4:58 PM, Jeff Janes <jeff.janes@gmail.com> wrote:
On Sun, Oct 18, 2015 at 5:31 PM, Thomas Munro
<thomas.munro@enterprisedb.com> wrote:Hi
Here is a new version merging recent changes.
For reasons I do not understand, "SET work_mem " does not complete with
"TO".But if I change:
else if (Matches2("SET", MatchAny))
to:
else if (TailMatches2("SET", MatchAny))
Then it does.
Thanks for taking a look at this! The word count returned by
get_previous_words was incorrect. Here is a corrected version.
--
Thomas Munro
http://www.enterprisedb.com
Attachments:
Here is a new version merging the recent CREATE EXTENSION ... VERSION
patch from master.
(Apologies for sending so many versions. tab-complete.c keeps moving
and I want to keep a version that applies on top of master out there,
for anyone interested in looking at this. As long as no one objects
and there is interest in the patch, I'll keep doing that.)
--
Thomas Munro
http://www.enterprisedb.com
Attachments:
On Wed, Oct 21, 2015 at 8:54 PM, Thomas Munro
<thomas.munro@enterprisedb.com> wrote:
Here is a new version merging the recent CREATE EXTENSION ... VERSION
patch from master.(Apologies for sending so many versions. tab-complete.c keeps moving
and I want to keep a version that applies on top of master out there,
for anyone interested in looking at this. As long as no one objects
and there is interest in the patch, I'll keep doing that.)
I don't want to rain on the parade since other people seem to like
this, but I'm sort of unimpressed by this. Yes, it removes >1000
lines of code, and that's not nothing. But it's all mechanical code,
so, not to be dismissive, but who really cares? Is it really worth
replacing the existing notation that we all know with a new one that
we have to learn? I'm not violently opposed if someone else wants to
commit this, but I'm unexcited about it.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Robert Haas <robertmhaas@gmail.com> writes:
On Wed, Oct 21, 2015 at 8:54 PM, Thomas Munro
<thomas.munro@enterprisedb.com> wrote:(Apologies for sending so many versions. tab-complete.c keeps moving
and I want to keep a version that applies on top of master out there,
for anyone interested in looking at this. As long as no one objects
and there is interest in the patch, I'll keep doing that.)
I don't want to rain on the parade since other people seem to like
this, but I'm sort of unimpressed by this. Yes, it removes >1000
lines of code, and that's not nothing. But it's all mechanical code,
so, not to be dismissive, but who really cares? Is it really worth
replacing the existing notation that we all know with a new one that
we have to learn? I'm not violently opposed if someone else wants to
commit this, but I'm unexcited about it.
What I would like is to find a way to auto-generate basically this entire
file from gram.y. That would imply going over to something at least
somewhat parser-based, instead of the current way that is more or less
totally ad-hoc. That would be a very good thing though, because the
current way gives wrong answers not-infrequently, even discounting cases
that it's simply not been taught about.
I have no very good idea how to do that, though. Bison does have a
notion of which symbols are possible as the next symbol at any given
parse point, but it doesn't really make that accessible. There's a lack
of cooperation on the readline side too: we'd need to be able to see the
whole query buffer not just the current line.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Tom Lane wrote:
What I would like is to find a way to auto-generate basically this entire
file from gram.y. That would imply going over to something at least
somewhat parser-based, instead of the current way that is more or less
totally ad-hoc. That would be a very good thing though, because the
current way gives wrong answers not-infrequently, even discounting cases
that it's simply not been taught about.
I did discuss exactly this topic with Thomas a month ago or so in
private email, and our conclusion was that it would be a really neat
project but a lot more effort than this patch. And after skimming over
the patch back then, I think this is well worth the reduced maintenance
effort.
I have no very good idea how to do that, though. Bison does have a
notion of which symbols are possible as the next symbol at any given
parse point, but it doesn't really make that accessible. There's a lack
of cooperation on the readline side too: we'd need to be able to see the
whole query buffer not just the current line.
At the current pace, a project like this might take years to
turn into a real patch. My own vote is for applying this for the time
being.
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Thu, Oct 22, 2015 at 02:36:53PM -0700, Tom Lane wrote:
Robert Haas <robertmhaas@gmail.com> writes:
On Wed, Oct 21, 2015 at 8:54 PM, Thomas Munro
<thomas.munro@enterprisedb.com> wrote:(Apologies for sending so many versions. tab-complete.c keeps moving
and I want to keep a version that applies on top of master out there,
for anyone interested in looking at this. As long as no one objects
and there is interest in the patch, I'll keep doing that.)I don't want to rain on the parade since other people seem to like
this, but I'm sort of unimpressed by this. Yes, it removes >1000
lines of code, and that's not nothing. But it's all mechanical code,
so, not to be dismissive, but who really cares? Is it really worth
replacing the existing notation that we all know with a new one that
we have to learn? I'm not violently opposed if someone else wants to
commit this, but I'm unexcited about it.What I would like is to find a way to auto-generate basically this entire
file from gram.y.
I've been hoping we could use a principled approach for years. My
fondest hope along that line would also involve catalog access, so it
could correctly tab-complete user-defined things, but I have the
impression that the catalog access variant is "much later" even if
autogeneration from gram.y is merely "soon." I'd love to be wrong
about that.
That would imply going over to something at least
somewhat parser-based, instead of the current way that is more or less
totally ad-hoc. That would be a very good thing though, because the
current way gives wrong answers not-infrequently, even discounting cases
that it's simply not been taught about.
Indeed.
I have no very good idea how to do that, though. Bison does have a
notion of which symbols are possible as the next symbol at any given
parse point, but it doesn't really make that accessible. There's a lack
of cooperation on the readline side too: we'd need to be able to see the
whole query buffer not just the current line.
This may be on point:
I suspect we might have to stop pretending to support alternatives to
libreadline if we went that direction, not that that would necessarily
be a bad idea.
Cheers,
David.
--
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david.fetter@gmail.com
Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
David Fetter <david@fetter.org> writes:
On Thu, Oct 22, 2015 at 02:36:53PM -0700, Tom Lane wrote:
I have no very good idea how to do that, though. Bison does have a
notion of which symbols are possible as the next symbol at any given
parse point, but it doesn't really make that accessible. There's a lack
of cooperation on the readline side too: we'd need to be able to see the
whole query buffer not just the current line.
This may be on point:
I suspect we might have to stop pretending to support alternatives to
libreadline if we went that direction, not that that would necessarily
be a bad idea.
Given the license issues around GNU readline, requiring it seems like
probably a non-starter.
It strikes me though that maybe we don't need readline's cooperation.
I think it's already true that the previous lines of the query buffer
are stashed somewhere that psql knows about, so in principle we could
sew them together with the current line. That might be a project worth
tackling on its own, since we could make the existing code smarter about
multiline queries, whether or not we ever get to a grammar-based solution.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Thu, Oct 22, 2015 at 7:05 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
I think it's already true that the previous lines of the query buffer
are stashed somewhere that psql knows about,
Just skimming but:
"""
\p or \print
Print the current query buffer to the standard output.
"""
http://www.postgresql.org/docs/9.4/interactive/app-psql.html
David J.
On Thu, Oct 22, 2015 at 04:05:06PM -0700, Tom Lane wrote:
David Fetter <david@fetter.org> writes:
On Thu, Oct 22, 2015 at 02:36:53PM -0700, Tom Lane wrote:
I have no very good idea how to do that, though. Bison does have a
notion of which symbols are possible as the next symbol at any given
parse point, but it doesn't really make that accessible. There's a lack
of cooperation on the readline side too: we'd need to be able to see the
whole query buffer not just the current line.This may be on point:
I suspect we might have to stop pretending to support alternatives to
libreadline if we went that direction, not that that would necessarily
be a bad idea.Given the license issues around GNU readline, requiring it seems like
probably a non-starter.
I should have made this more clear. I am not an IP attorney and don't
play one on TV, but this is what I've gotten out of conversations with
IP attorneys on this subject:
- If we allow people to disable readline at compile time, the software
is not GPL even if only libreadline would add the command line
editing capability.
- When people do compile with libreadline, the only software affected
by libreadine's license is the binary to which it is linked, namely
the psql client.
To be affective negatively by libreadline's viral license, an entity
would need to fork the psql client in proprietary ways that they did
not wish not to make available to end users, at the same time linking
in libreadline.
Maybe I'm missing something big, but I really don't see people out
there shipping a libreadline-enabled psql client, details of whose
source they'd want to keep a deep, dark secret.
If this gets to matter, we can probably get /pro bono/ work from IP
attorneys specializing in just this kind of thing.
It strikes me though that maybe we don't need readline's
cooperation. I think it's already true that the previous lines of
the query buffer are stashed somewhere that psql knows about, so in
principle we could sew them together with the current line. That
might be a project worth tackling on its own, since we could make
the existing code smarter about multiline queries, whether or not we
ever get to a grammar-based solution.
Great!
Cheers,
David.
--
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david.fetter@gmail.com
Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
David Fetter <david@fetter.org> writes:
On Thu, Oct 22, 2015 at 04:05:06PM -0700, Tom Lane wrote:
Given the license issues around GNU readline, requiring it seems like
probably a non-starter.
I should have made this more clear. I am not an IP attorney and don't
play one on TV, but this is what I've gotten out of conversations with
IP attorneys on this subject:
I'm not an IP attorney either, and the ones I've talked to seem to agree
with you. (Red Hat's corporate attorneys, at least, certainly thought
that when I last asked them.) But the observed facts are that some
distros refuse to ship psql-linked-to-readline, and substitute libedit
instead, because they got different advice from their attorneys.
If we desupport libedit, the end result is going to be these distros
shipping psql with no command-line-editing support at all. Our opinion,
or even our lawyers' opinion, is unlikely to prevent that outcome.
While libedit certainly has got its bugs and deficiencies, it's way better
than nothing at all, so I think we'd better keep supporting it.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On 2015-10-22 16:26:10 -0700, David Fetter wrote:
To be affective negatively by libreadline's viral license, an entity
would need to fork the psql client in proprietary ways that they did
not wish not to make available to end users, at the same time linking
in libreadline.
Maybe I'm missing something big, but I really don't see people out
there shipping a libreadline-enabled psql client, details of whose
source they'd want to keep a deep, dark secret.
Isn't that just about every proprietary fork of postgres? Most have
added backend features and I guess many of those have in turn added
support to psql for those features. Sure it'd probably in reality be
relatively harmless for them to release these psql modifications, but I
rather doubt their management will generally see it that way.
Greetings,
Andres Freund
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Thu, Oct 22, 2015 at 8:09 PM, Andres Freund <andres@anarazel.de> wrote:
On 2015-10-22 16:26:10 -0700, David Fetter wrote:
To be affective negatively by libreadline's viral license, an entity
would need to fork the psql client in proprietary ways that they did
not wish not to make available to end users, at the same time linking
in libreadline.Maybe I'm missing something big, but I really don't see people out
there shipping a libreadline-enabled psql client, details of whose
source they'd want to keep a deep, dark secret.Isn't that just about every proprietary fork of postgres? Most have
added backend features and I guess many of those have in turn added
support to psql for those features. Sure it'd probably in reality be
relatively harmless for them to release these psql modifications, but I
rather doubt their management will generally see it that way.
Yeah, exactly. EnterpriseDB have to keep libedit working even if the
PostgreSQL community dropped support, so I hope we don't decide to do
that.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
* Tom Lane (tgl@sss.pgh.pa.us) wrote:
David Fetter <david@fetter.org> writes:
On Thu, Oct 22, 2015 at 04:05:06PM -0700, Tom Lane wrote:
Given the license issues around GNU readline, requiring it seems like
probably a non-starter.I should have made this more clear. I am not an IP attorney and don't
play one on TV, but this is what I've gotten out of conversations with
IP attorneys on this subject:I'm not an IP attorney either, and the ones I've talked to seem to agree
with you. (Red Hat's corporate attorneys, at least, certainly thought
that when I last asked them.) But the observed facts are that some
distros refuse to ship psql-linked-to-readline, and substitute libedit
instead, because they got different advice from their attorneys.
The issue for Debian, at least, isn't really about libreadline or
libedit, it's about the GPL and the OpenSSL license. From the Debian
perspective, if we were able to build with GNUTLS or another SSL library
other than OpenSSL (which I know we've made some progress on, thanks
Heikki...) then Debian wouldn't have any problem shipping PG linked with
libreadline.
If we desupport libedit, the end result is going to be these distros
shipping psql with no command-line-editing support at all. Our opinion,
or even our lawyers' opinion, is unlikely to prevent that outcome.While libedit certainly has got its bugs and deficiencies, it's way better
than nothing at all, so I think we'd better keep supporting it.
I agree that it's probably not a good idea to desupport libedit.
However, I don't believe supporting libedit necessairly prevents us
from providing better support when libreadline is available.
Debian-based distributions won't be able to reap the benefits of that
better support until we remove the OpenSSL dependency, which is
unfortunate, but other distributions would be able to.
Also, if the PG project is agreeable to it, there's no reason why we
couldn't provide full libreadline-enabled builds off of
apt.postgresql.org, regardless of what Debian wants. That would add a
bit of extra burden on our package maintainers, as there isn't any
difference between packages built for Debian and packages built for
apt.p.o currently, I don't believe, but it seems like it'd be a pretty
minor change that would be well worth it if we get better libreadline
integration.
The one bit of all of this that worries me is that we would take
libreadline for granted and the libedit support would end up broken.
That seems a relatively minor concern though, as it sounds like there is
a fair bit of exercise of the libedit path due to the commercial forks
of PG which make use of it to avoid the GPL.
Thanks!
Stephen
Stephen Frost wrote:
The issue for Debian, at least, isn't really about libreadline or
libedit, it's about the GPL and the OpenSSL license. From the Debian
perspective, if we were able to build with GNUTLS or another SSL library
other than OpenSSL (which I know we've made some progress on, thanks
Heikki...) then Debian wouldn't have any problem shipping PG linked with
libreadline.
What if OpenSSL were to switch to APL2?
/messages/by-id/20150801151410.GA28344@awork2.anarazel.de
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
* Alvaro Herrera (alvherre@2ndquadrant.com) wrote:
Stephen Frost wrote:
The issue for Debian, at least, isn't really about libreadline or
libedit, it's about the GPL and the OpenSSL license. From the Debian
perspective, if we were able to build with GNUTLS or another SSL library
other than OpenSSL (which I know we've made some progress on, thanks
Heikki...) then Debian wouldn't have any problem shipping PG linked with
libreadline.What if OpenSSL were to switch to APL2?
/messages/by-id/20150801151410.GA28344@awork2.anarazel.de
According to that post, it would depend what libreadline is licensed
under. There may be other complications with GPL3 and other libraries
we link against, though I can't think of any offhand and perhaps there
aren't any.
Thanks!
Stephen
On Fri, Oct 23, 2015 at 02:09:43AM +0200, Andres Freund wrote:
On 2015-10-22 16:26:10 -0700, David Fetter wrote:
To be affective negatively by libreadline's viral license, an entity
would need to fork the psql client in proprietary ways that they did
not wish not to make available to end users, at the same time linking
in libreadline.Maybe I'm missing something big, but I really don't see people out
there shipping a libreadline-enabled psql client, details of whose
source they'd want to keep a deep, dark secret.Isn't that just about every proprietary fork of postgres?
Proprietary versions of the psql client? I'm not sure I understand.
Proprietary, secret changes to the back end, sure, but the client?
The most recent example I recall of that is Netezza, and I suspect
that they just couldn't be bothered to publish the changes they made.
At that time, the community psql client was not by any means as nice
as it is now, so it's conceivable that they made substantive
improvements, at least for talking to Netezza DBs.
Most have added backend features and I guess many of those have in
turn added support to psql for those features. Sure it'd probably
in reality be relatively harmless for them to release these psql
modifications, but I rather doubt their management will generally
see it that way.
Is it really on us as a community to go long distances out of our way
to assuage the baseless[1]as far as I know, and I'll take this back in its entirety if someone shows me a reasonable basis -- David Fetter <david@fetter.org> http://fetter.org/ Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter Skype: davidfetter XMPP: david.fetter@gmail.com paranoia of people who are by and large not
part of our community?
As to our "support" of libedit, feel free to try working with a psql
client that has libedit instead of libreadline for a few weeks. It
would be a very long stretch, at least for the work flows I've seen so
far, to call that client functional. The strongest praise I can come
up with is that it's usually not quite as awful as working with a psql
client entirely devoid of command line editing support.
Of course, we can continue to pretend that there is a viable
alternative to libreadline if that soothes down some feathers, but I
don't see any reason to make substantive sacrifices in service of
keeping that particular box checked.
Cheers,
David.
[1]: as far as I know, and I'll take this back in its entirety if someone shows me a reasonable basis -- David Fetter <david@fetter.org> http://fetter.org/ Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter Skype: davidfetter XMPP: david.fetter@gmail.com
someone shows me a reasonable basis
--
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david.fetter@gmail.com
Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Oct 23, 2015 at 11:16 AM, David Fetter <david@fetter.org> wrote:
Proprietary, secret changes to the back end, sure, but the client?
The most recent example I recall of that is Netezza, and I suspect
that they just couldn't be bothered to publish the changes they made.
At that time, the community psql client was not by any means as nice
as it is now, so it's conceivable that they made substantive
improvements, at least for talking to Netezza DBs.Most have added backend features and I guess many of those have in
turn added support to psql for those features. Sure it'd probably
in reality be relatively harmless for them to release these psql
modifications, but I rather doubt their management will generally
see it that way.Is it really on us as a community to go long distances out of our way
to assuage the baseless[1] paranoia of people who are by and large not
part of our community?
I was under the impression that I was part of this community, and I
have already said that my employer has added tab completion support,
and other psql features, related to the server features we have added.
Also, your statement that this is a long distance out of our way does
not seem to be justified by the facts.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Fri, Oct 23, 2015 at 12:15:01PM -0400, Robert Haas wrote:
On Fri, Oct 23, 2015 at 11:16 AM, David Fetter <david@fetter.org> wrote:
Proprietary, secret changes to the back end, sure, but the client?
The most recent example I recall of that is Netezza, and I suspect
that they just couldn't be bothered to publish the changes they
made. At that time, the community psql client was not by any
means as nice as it is now, so it's conceivable that they made
substantive improvements, at least for talking to Netezza DBs.Most have added backend features and I guess many of those have
in turn added support to psql for those features. Sure it'd
probably in reality be relatively harmless for them to release
these psql modifications, but I rather doubt their management
will generally see it that way.Is it really on us as a community to go long distances out of our
way to assuage the baseless[1] paranoia of people who are by and
large not part of our community?I was under the impression that I was part of this community, and I
have already said that my employer has added tab completion support,
and other psql features, related to the server features we have
added.Also, your statement that this is a long distance out of our way
does not seem to be justified by the facts.
As I wrote in the part you cut, we can continue to pretend libedit is
a viable alternative if it keeps some feathers unruffled. If libedit
"support" gets to be a real drag, we can and should reconsider with a
strong bias to dropping it.
Cheers,
David.
P.S. With a little luck, our next license or other perceived legal
conflict will be as easy to sort out as this one. I have the sinking
feeling that anything we do with crypto or hashing more secure than
MD5 will run afoul of someone's idea of what the law is in their
country, and the impacts will be a lot nastier than this. We will
need to deal with that separately, as needs arise.
--
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: david.fetter@gmail.com
Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
David Fetter <david@fetter.org> writes:
Is it really on us as a community to go long distances out of our way
to assuage the baseless[1] paranoia of people who are by and large not
part of our community?
While I personally don't care that much about the proprietary-psql-variant
scenario, I do care whether people using Debian packages will have a good
experience with psql.
And frankly, sir, you do not have the standing to call their fears
baseless. You can believe that they are, and you might even be right,
but your opinion on such matters does not matter to them.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sun, Oct 18, 2015 at 9:12 PM, Thomas Munro <thomas.munro@enterprisedb.com
wrote:
Thanks for taking a look at this! The word count returned by
get_previous_words was incorrect. Here is a corrected version.
I haven't looked at v6 yet, but in v5:
"set work_mem TO" completes to "NULL" not to "DEFAULT"
line 2665 of the patched tab complete file,, should be "DEFAULT", not
"NULL" as the completion string. Looks like a simple copy and paste error.
For the bigger picture, I don't think we should not apply this patch simply
because there is something even better we might theoretically do at some
point in the future. Having used it a little bit, I do agree with Robert
that it is not a gigantic improvement over the current situation, as the
code it replaces is largely mechanical boilerplate. But I think it is
enough of an improvement that we should go ahead with it.
Cheers,
Jeff
Jeff Janes wrote:
For the bigger picture, I don't think we should not apply this patch simply
because there is something even better we might theoretically do at some
point in the future.
Agreed.
Having used it a little bit, I do agree with Robert
that it is not a gigantic improvement over the current situation, as the
code it replaces is largely mechanical boilerplate. But I think it is
enough of an improvement that we should go ahead with it.
To me this patch sounds much like 2eafcf68d563df8a1db80a. You could say
that what was replaced was "largely mechanical", but it was so much
easier to make mistakes with the original coding that it's not funny.
--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
On Sat, Oct 24, 2015 at 6:19 AM, Jeff Janes <jeff.janes@gmail.com> wrote:
On Sun, Oct 18, 2015 at 9:12 PM, Thomas Munro
<thomas.munro@enterprisedb.com> wrote:Thanks for taking a look at this! The word count returned by
get_previous_words was incorrect. Here is a corrected version.I haven't looked at v6 yet, but in v5:
"set work_mem TO" completes to "NULL" not to "DEFAULT"
line 2665 of the patched tab complete file,, should be "DEFAULT", not "NULL"
as the completion string. Looks like a simple copy and paste error.
Indeed. Thanks. Fixed in the attached.
--
Thomas Munro
http://www.enterprisedb.com
Attachments:
tab-complete-macrology-v7.patch.gzapplication/x-gzip; name=tab-complete-macrology-v7.patch.gzDownload
���*V tab-complete-macrology-v7.patch �}kwI��g�W����P�d�����#,s����nN J2�
����7��U�YY����s���+����?���.�/��������K��x8{�O�e�b���~}6���?�Ip>*_T_������_F����J����q������,3����R��;EG���s����?�o�����~
B��]����YX,=�C0�_��X���I�?��O�I�
'������5
��� �y�w����8\�
a�Ca��9���K9����
?���<�]>|��'b�<��m���?�~�2I���$]���a0�i8^�?���? ��j2�H��t� �����K�+�������D��w��j! DX����%2N5���?�B���)g����m1��w)C�3����]���%]X����}D��%GO ���/��ex�oo������0x��<�1�q��Ct?[����#����4~I�����w��.�����@E��a��������/���BSP�z1�.�����G ��?�H��C�3Qi~s���d�����k��W���.�g�z���"�<���YfXO�h>���x��
<DZL�g<��|��h(� 2�&��<����b�?���E�h��U�zA�1�b��'���?���Q c�}��ItwL�#L���`�;����$���>��=Z~
����8���_#��Y���_.�����C�B�"�>��$y��������0K�y?4���W������t�/��h�/F��������i�R��n6�<;��&v��/>Y��Hk��Iw�����"?�H��A�[�c��MA'����j���r5=��D��|�$�t�U��0�O���F�����|����o�)f���,O%���f������F"��X
"�9�*s�"6���i�� p��O���"X��W�'�����o'x.(��������}����i�����S`��H��C���5�q2�,�t�d>����F��TA���s��)�t�����t���f�,{&�b+��|���M� VA����d2�~E����p����#t��GGC��OJ>W�>�;�%�� W�S��P���xP�,������v�O��L�k�a��LH�>�����3�\�B1Z#��gtB�~���G��!]9��P�S��h�~5�'�*�.�E"��'���R�>Q�� ��+�#�#��H��d"� ���������1��G����t�?bc�E�(�$�G��Cx�qi���#��Gl� MW�w��g|��0Gb�4��:]bj�G����K�Q���XxRY:\N�S���d<�_*4B�)�a,�����?2 ��D~|aH
��'��J�]�Y7��)�i�'�Eq��S�k�<K��B���c�<uM�r
�l"�T}���'���(�Ej�(��9��8�������k���.�
P�A��8><4LP.�����I�-��E9k��k�_u)������ja�U�op��U����ia�o�-X����i�g�9�V���oq�Z�e���0�7��A����'#/
s|e� r�)�oq���9���A�8���C��"5y.�F)1��2F*%F�]����O��#�#���G�(?F���9�5��7�V�R[�C���&�ZEi�@tu���P�|���>B�B��Y`��02��}�2C28����/�!3t��{��W�n�C��V��������n���W�6�P���r�i�i�z��k��=��U�\_7x���?����v�>�t���Z������u�Gv��V���xz��J�\j��?����u_��_�������]�����5:>Fw��7.���l�/�<4�-�\1�� ���;1�.���1��+ p��\�E]�/�d�
3���g���S�e���M��m���e���Y5����f#X���I����
M��:��y���&��Y"���g��$�������
b��� b&�5?E���pJ��x#\T�>�> � �!�����fa��� z��i��p�(�C�B0��/��I��h��������d��A���n�>������Vrf6��'D3C��D����GG�n�{L�;�{8��O��G��&��-/��U�JL����J�t�pS�y�+�U*���&���?��Mg,n�Wg6���;?�"�& !�E�k�r���)�)e���8�"����7���7�V��/�GC"�}*�v���}
K#e.�!��l���
��'�G������q.V�d�'K���!�ht��C0
�r��@]v;7� ��}�
���(����"�l���l��L�������'�&2F�`��� ���U(�J�w�����Sb�0�" �t:���1����^*D:��a�V]�k���6��'������>�f��%fAH��?���m��i�^������VP�� ������}��c�M�`���
OAvB4��CW��-���^���/^��/!$2y��0��X���o)b���x9�����L�U��������h�$T��|y��D-%M��_���6���X��Z�>& ��������.kx�Z�k��k��>��6�6[��F�~����
��I��+V�DLWO���NV���`!���Hb�x��e�W���m�Z��n\����;�����om�������6-)�A��� ��5�+C��N){L(�k� �:�� ��-��?��E�fbW�w��e+�p��U�d��5k���Vg�����p
W�3]9x�0�4?��JN�G�lC��_���r;��4���v��7�����(�A�qJ��������ba�&]V�C9�Z��q|
mX��
�_H��=zt�eIew$���T�")�.*�TU���K��x�>8<8����"#���t����7�(��n�]�n�?�4b�LBNZ��ez��@ �� ��@�������Q�a�(�"��A�{%�Z�*�������{I���$�j��3�����G�<���,�n=����n��R��)�#�mG�6o��a^�;����M�����i!U������j���Ni!/,��]#rt��O�P7{�~�^�H_�ku��S������q��D�&���i)V&�ru�&�Y
(s�����t�FmSP'�����W�n���B��t
�����T��fS�����s0]����C�c�-��[(K=4b���Y��6�
� ���l���c����J��~�5Q���pg ���2�J���+N�.��m�H�MYc��Q��M�Y�1�����������P����I�L/<� ����k,r���}#z�.���Z����7��\�����g]`{BV�$��N���j������MxWEv�C���nnT�����Cf�^}��7��~I&���[ ���c�.�����K������"r���/[mok�&^C�����:�r�8��X� D (�6�&�`�4�Ty����-��=�/9N8bw��@D� �t�������.�H��7�.������y�;���b�T����$TWj�����#;>e�>�O�4�H���$>vy����>����c����>� ![g��#9�w"XTBX��.2�p��l������`��Q�F�6�\[Q(���p�{
J��w!�����2�����UH�
����x\�!�������sM"b���dr������.W����_��`����\���K�Q��O�
����a�`A���
����nkW����Ir/�u�o?bH�1#�}��8�Z������N���x�#���w*���E$<
����i�@���-?E$�85^)��#;��4�c������F���>������fnz������_����|
�y��F�^��j�}�:�`��Nt�8��������I�?,h�*���\I��r���M����LOP����U��-��Kg�xB������8��j�]%ei�j�*]��M\FV����9��4I��O� �+
,�7�0�i�7Ez������S�*"(�0z_�H�KL����Q��$�\����v�����w�����/��w����\�:�d*��"�����94��l}�%�l$�[��6�>�5���������<��R�A�ac��
�Q"��u��8J�g!�������� �~�1���tY��;~���t���
&n�@]��v�XX��F�P��M�N+�z�8����j���',C�$�IN�� �5��[��,K"�\U���������x���67'������f�fE��qz��$���A�a�+8�2����P���w�h��]����:muP�������q���(m���.�y@�����lg����~fy�9T
Z����N�RD�������)%� Z�K�$E%`����\���������'�����_B�������`���+2
�U ]���OL /xJ��xz?�!�b��hw �����>m�4��q1��V�o`o��
�5��-q1�(gJ��I/����W"��b�+Vv�(
������jk@�u� �F��rD�����uc(�����{�es��.�a��~�#otl��v��J�'V��%Y����)1��%��KN�?�.�v��y{��m|*�6�i�W��\j]�:�'jk���zd�-_�y� ���.����d��#-���kwv����n7�7��&&QTE�8!��M�
�q��u2"� f�r��Mn��[�Se�
G��c�a=#*(96uvdC��� (����7����1���]��o�0���cr9{�q���b��L�\n���Ny\���) �-�q��h�|-^��$K�2=�*��)\��0X>�4I�2}.�%fS/�0~%��]k����n��"�T������H���8m�~
�t�vso���x��J`>����`���*�o:�f�� u���k[�Yth�t�#!H?f��7�BjG���z�*�Rv�Ha��;�+>C�1
?�����$�����R
y����P#�����{�#�1��@4���~g3��9
Tlx����w��H���8u�m����m����:uA6�A�yX���LV�4%�����3c����� �b7�4�w8b����Q%��"�-�C��6�B�I�����UEl�V�Ny��vv���N~�����yX����9H��A�����������`�D��H���
��UHR���P �(W�W��D�8 ���s� ^����-�c~<��n�N21�}�hSL�6����J��u���06��r����IlT�\T��F��"�lJ:I.��Mv��*�JmWJi�[l��b���A`���,v�e�X^��r��%0Kq�)��Q��pu'3fC8.�P��D�&��%s�;/��x��(��5��Z9�JgXBT�XB���{C+r�����>���B��%�If���x�47��;�j�m�P�Q��tx������'�Q��@PDFI�
�u_@
����?���la�;��8,A��O�n�F����J� �,I��@w��(��<_~4/���h�����w��� � \H�n�5�\9���E��-(@^+���N��U]�����������9��K��-~�7����a����n(2��Z���y��F%4N{0������s�kb�"��;`�}�!=���a��`�v;�������MqU����z��q[V����Z��W�K��&3�����%���=oEEQ����(Gt���w`TS����s�v�Q|����]����K��n4���G�*����-���F,+e����_Z�C��j|��Z���*��x��u��V��d�o�ANNt�q�`P
q�2
��;z�3}��fg���z��eH��� �}��-���/�7Y=NA��,a��v�(��R?=+M`�F;�����Y���OOO�q�>���U�r�J|�I�X���I�����
�B�����^*�w
����)`� 1��t���D��
��`���3Q��|����
��f���\�.�(v:<����Wa�4r4���Nc5��
�E '���y��#C���QB[(x�S�vC���� ��B��^[rx�D1�YD�9� �u�v��;�0����YZ��c��<��5�_��B����BI6G��<~�R��lM�g$���o�-2%0����Rv�����A�,��=6My_=��#��3B�,��*p3�9e� ����@�~��9�Y���:]���h.��Sl&!�'�p�����Z��'&]�u��u��8���� f���t��-�`g+O%a�F���tH��+���S�/����f]71�O/������c
��q������.�!�X���nZ,Y ���G����d��<����cSl��"@]9O�4�0��,�I���|������y�|r�h�W�<��)�`���1��&'w�!�����R!!�Ml�ZG�V�3 �"��W9Z�J{�3X�h��}�_.���2�?����N�i�z2�Y�R�[��+&#e��x����v�F���;�N�7����g��{V� 3]��J�Ik_R�����a`7���U��ZQ*�����:�CL�� N9�#+4e�-P�yiO��kTJ����������p9�k�,3% F�ube:��iC�d���E��b����
�K-�|��R��+��@Ht$�ZK��X�y��+UN�Q����+�\lB�D�.���'�b}hl^6�����.L�� WM���pJ��\��d�P�vZu��:�.�q��(��#M
�'�V�d�=C�pz�*�4-�����y�T���B|y�9O��n�dr�]]��(�x�)o�2@��x]���`2�.M�1E7eg-$�h=$2jyJ��F���O�_u�wS7$8Rs����H�?
�.n��k�(#*�"�dw�z*i����i)����;*���o�^l���{E�c0�����������c����>.����xF^����"����6��`���k2)����W\��>f�Z��,��-y�'���:��]< �+��yu����"� ��X�R�����U��
Lb�^��r��E��W�`��%�������*��U�p6�����+��m�!#jEr�&<��rUe���q)� �+��S�sE�z����+"I6�u*p���ZA�It���X���J��2[W-�����d������y��y�ZX��|��p�S�(�J�����?�����E��w�o[�o�|u��)����*�;���
�\�-����o]����gW0#vH��Q�.����dr'��w5���wy�9+�X���+f� L�Q���E3�
#����"������������ DI��Q�dk��$�����o�l7�&6�si�t #��(
�%^/�40F�
.1��v�
�|�R�qJ�cZ��8�vE�B@��]=r]9����;$q,^u;�7ZP��&� r�Q�/�(���T)�J"X����Z��i�NT2�Q(s3��E���l�(v�����Z'��[�>o�
�K�������L�C�0X ��P��\0���v�y����������IV5x�0�_5��m5�����t�,l��_/��xthS�G{}�����u��Pe�|]��/��Nzd��b�����RM��n��x��dZ��D���>6���t7�.����!�Qm�5IW�Z8���V��k�^�m�����g�W�B��,���rQ�V�U��p)�����fr�����M�<�� ����� %�dF'�V!�2[��8�����t�T}#G�a�p5�(����J������XP��_b� �X��������r�D�����mt_uz
]n�VC�/"�R�sc|�qr����w��s��Y<��r���?%U?�Z�������������'�/5[F2QF*�j�]v�5��I����r���6��K�A�{Wz�A�uX!�D��C�|������C�}Gv��s*������m�G�u�����'�H2��]�x��-���2���Rq$J�Q,��X�p�W�'��5�XG���:�l�Q�VI7���W�h}^"�����^Q��z���p�gQ�R:������Q"�7�TG�SY 'k��X��;%�����W���M��9��]v$A����Z�;�F��������A2z�����s��5jP���#.��}%��$�v�����K��'[��I�A���Z������_���5�I�r��� ;Q�TA���������>u��4����!w�vY6@��yY��'y���$\�lQS;�5�r�\�LVK�s��"y�[����<�D����mK$pPp"c��T�0���s0]�l����S��������'�K�����W���_V�=���B�H��S��l9��j��m��0%>m�2��z������yO�j��pq�U���e�r��J��K\��<^5�b��|?����`�~_���i��a0�?����>X���fHT�M��H?z���d�@,�w���p���De�C0^"�m������S�u���&�i�a���J��7��r)�5J^Io�'���g��G�g���|�/��,��!�
�_w;�p�)��,b��������;J�'�sp cd>��b�x��*+�� ��k�(�E)u?�V���b��d>t�T2������@� �g�wl��l��Q�O��B3���:�#���_���/f�B�0^��
�g��:P��D��#+�,9����!�)��}��%EE����F�y���T���{K��v�s �&S�\=����� K��g-<�<���]k�N�/�%}�mD�7��%C��o;�]����X����n����O�$m��6W�4q�L�J7XuD�z�Aw2���v��� ��+z%��Bu'&rW5{��!]�~����#zo�A�Z=ni�"�I�w������/��J�������c2n�������C/���@z ����b���K������%}W� ���z�c�.Lm0�C[�1]����I�k���`�����/3�F�O�E
o��$��4_��f ��qD>���$"�N8� "������T�#��v��Y����������b�����H� %�������\]x;�#��0H�����
a�H��7kv��s��v�� ���v��s=�r�}��X�zA�$�������EyE�s���H��n@P���@��\k_��{ +��Vi����$Mi�X�qD����d��~=^P{#5�H# oz�n�-��[,��n�(���h= Y�RV":��G���{X(R����1�V��\� y\�^���L�����U�}/�%��2��'u���~�*��i�g6�T��v��v��� :w��x��s�v�~D�3vI���V�-��ul�B�~��e����a]��o��-�����;�w
���S'7�W���T�PN�O�A��Tk���I�����Tpc6T��u2��3����t�=cVI�v:��p��EJP�[���G!H����.�zAE��Z'+���C6R�i����"�7�'tGy��_`�Z��g��@����,���Iw��RJ��w�BG��`���Xq�y%�DXK@�h�d)�V�8� �I!_V�����"F��y2������!y*�}���|�$���Y9��9%����ZHA.v�2��c(`�m�������.�N�����r���p�c��c�k� �D� �~7us1~�A�C`A�4r��|q�i5�i��t]"s��J��=CJ�v��e �� �}��HRPw�����sc6���A?���g��nn�8�!��na
�B���!�g
�A��"I8�?�8I�QG���~gM������l�_�(�g���4���O%K�yY�7Y�A����F�
�$,���t����u��ZkfZ7��F����!u���
��}����+T�X���W��__*,S�UX)j�
�`��F��8r�2K&��:�� ����F.�������S�5RJ2��E�6
��;,zME�
d��]j���aU�������X1�A�|U^�(�@w�Tl='o�L�s�������"��f?i_��yX�!��g,&���q�1�'�$G ����v�v�"�x�&'�l�����w��H�3�5�S�"7�m�*�[h�xX��e�&�
���U����U�!�Z���d1�vo[
����J����/B��+�����@���
��yCG�Z������5(0�s��\,
l�������]��#���.���X�8�F'Wt[��H�� z�S���bhI$
Bz� h�iBR
R������C��}1����1�v9[����PXM���4Q�"N����Y�����Ue�� +��He�qs�fQb�t8&��D,{Hv�A��O�
3�#��h�<�)�%�O�K�z
<H�����e�2f��G����L�U0C�R�3���+`0��E�H6���P�}��n�e������s����1�Y�
��}�%+l\���~��j�;y�����%,O���� |a�0�V$�r�J�&��K�,��v'�Q�����.;%�� �p�Tr�v��v�XhxW��1q�`��a�?��3l��l���3���aO��yK2Z�2$������uU����z����w��b���>
���M�����l�
M�;�1��H����`��;qg���^Z ��8&?���p?�� 7�Ba���Y��h���f4��*������\]5.9�$�we�gr�}����`j6)��{1$����n���;��F����[��M���G�:��Cq���p��P��T��/��i���+ G?2��aGn�2���4�N%%��T�Y�
`2S�ye������+�8�(g��Xk99�C���_T�I�~�OR����(��s�IU'�'~��)��D��j���P���@�)�������.����� [���%��v�a6��<�����j�*S5����QF�AS����q:�uV%Tke��c�����=���2s+��~��]w�l�����4sH�9�&���5�9�LN]@�3�]ty����H
7~� �T�<"��5I����'�E���R�)�
c���q3������T�Lk�a��l���z)������@@�!_�d��*}������ =�j���L�����@�"M�|c����cY��[I�BXo��&*�}y@�hbl��>Q����� c�Fg<)���_uR��b����7.o�v��wN�C%������H����G�����������9����7ZL��>�z�lnu�����D�Q��jx����+�n�V��0�V)��������
�����-�2�$�1d���^#���5~���f���:��|h% :�:*T��n�C����Z��m�����������y�+�Q����mR(in2pu���u}����Y8&���^e{�n�0��\s��$�`D���� �
��N2���>�[-�h6=XF���E��?��`�0�Q9C�����I����rq�U6��zc��F��}�y��m���`��
����t��}��b,(_92�� �g-�n��3�����,m��*-�]���8�8u����)�������o@`s�S��?Yy9�E �1�\�Rt �
(�K����+Lj,�.�z����sk�Yqc5s ��������k���;��*pn��9����,����z���[���(�^��:���FG�G{�ZR97��`{h��o������k�j���.V7tG����[���o-�]������@��kw��a�����L���b��xd!I��x2R�i7������-���n�5
����{4��RGj@�6�����C�"���b6w�*L��ng0����E�3DRp\6���'J@��n��t5Z�cQ���7�2�:�+if�vE�o�=�����o& �Y�������3�Z^�w��`�5���M�EO�G��/�~��P6�����^��LT��*�7i�r�����W*F�|�O.6�aH!�g����pA��t�D�#��/�����E@�8,�8D���nI6Pax������4W)P����k"A�_�����],����.^'c�r@�
�?��#�L��S3��/C�QF���
%ONwJr}�e�\���DI�*R�
=����/4�9-ebNc��/���wr(��``�F&��Y�5�M�����`F��9P%����I���_�+�N����W��0��������e_�W�u/����vD0����t���B���'���fg��lt�h���}=�Q���Kg:�?���G���]5^8H\���K�������"�]2�G�>,��P��������V4LC6&�T��v(-u�e��������~��<�\�n7?�qc]�3;R�X�=���^�n����z2��
��
���V�������@:]v�kM��<�>�o�uG`��i��#�w�U�:�#a]��5H^���V^7WMw�j-��z�S�����oL�l<D����(���9lx���]���~]���%~��|]4�k8C��K4�X� ����Y�� 9���q�z�A%���^+�8���Sc�k&��Rn��$k��]H�5��k����ZS��&�f���r���d�R�u��f�u:�S6R��P0%#gY@
���+�r�eK`�:b�5c���:����I5&C���C�)�0V"�gQ>�|ui�!�UQ @��$�Q�6J���M��b�xv,TG���.T���B��h�����o� ��]��*��_S]��}K5��(@���Z�*�=���O�*j�l 5�]�b�y��q'Z� y��a%#�TR����$O�m�ZI�*k�p�L�8D�A�{%i.l-t��/��tl��������������y6��L+L� �� �N�&E���C�i����Sk�m�5C�Z��zUf���� u,�ENM��r��sh8l��h[ee�[��������*�g ������N qm�t��W|� %���s����rq���������|���I�U]@�|#^~evI�x��]P5QZDV����l2� �B��V6 YN�x|d }D�s�l�l�
_������OuG��[��X�k��s^�P�pIb�B�t~��@u�&�+��)����Rh���>���Le1g�}X���w�h�Hm���S�@��Z��+�����k�k]��E@*S��%u�P�e�I�EV>)�y'��T��{��|�R�b��v����������N�/����7<�E���� ���N�����]"_�}�z1��<�'����F�>_�WG������A�/��Xv���C����u�I������g��E9�5�����-%�����kVw�cu�K���/���j���
� y �n��o�S�u��&�.��J��4 ��u��������Z���� �o��*��Ic���/�Ml�������^�u��k�O�� �'��-A[����^|kK9�2��H1�B�V�������n�\_r�Ki#��R.�mn��ku�@vn�R� U�rL%�"����8
�{,un�������_(��j���`��c���K��'����dB�`�e�V1������?Q8{�*!Q��������/�>V������j� O����� �Q��T��x� �����������DbQ��\JG>��������Kz1}�aE�|�#���t�58^�mb�+��Mx]e���mb�Q�te�v������)����'c�-�/9�>����:�`C��f�I�qh'�;����<�@'���!(Q�!���M������4-C4�n�m���C���&"`��-������x<