select-comma-completion-v1.patch
application/octet-stream
Filename: select-comma-completion-v1.patch
Type: application/octet-stream
Part: 1
Patch
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/bin/psql/tab-complete.c | 44 | 1 |
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 90516a1..58e139b 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1473,6 +1473,35 @@ ends_with(const char *s, char c)
}
/*
+ * Get the last keyword matching a pattern.
+ */
+static const char *
+last_keyword(char **previous_words, int previous_words_count, const char *keyword_pattern) {
+ int i;
+
+ for (i = 0; i < previous_words_count; i++) {
+ if (word_matches(keyword_pattern, previous_words[i])) {
+ return previous_words[i];
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Was the last keyword one of the expected ones?
+ * E.g. last_keyword("SELECT|FROM|WHERE|GROUP|ORDER", "SELECT") is true if SELECT is the most recent
+ * of those key words to appear.
+ */
+static bool
+last_keyword_matches(char **previous_words, int previous_words_count, const char *keyword_pattern, const char *accepted_pattern) {
+ const char *last_kw = last_keyword(previous_words, previous_words_count, keyword_pattern);
+ if (!last_kw)
+ return false;
+ return word_matches(last_kw, accepted_pattern);
+}
+
+/*
* The completion function.
*
* According to readline spec this gets passed the text entered so far and its
@@ -1512,6 +1541,14 @@ psql_completion(const char *text, int start, int end)
#define prev8_wd (previous_words[7])
#define prev9_wd (previous_words[8])
+ /* Macro for matching last keyword, case-insensitively. */
+#define LastKeywordMatches(keywords, pattern) \
+ (last_keyword_matches(previous_words, previous_words_count, keywords, pattern))
+
+ /* Macro for determining (loosely) which part of a DML query we are currently in. */
+#define CurrentQueryPartMatches(pattern) \
+ (LastKeywordMatches("SELECT|INSERT|UPDATE|DELETE|FROM|WHERE|GROUP|ORDER|HAVING", pattern))
+
/* Macros for matching the last N words before point, case-insensitively. */
#define TailMatches1(p1) \
(previous_words_count >= 1 && \
@@ -1738,6 +1775,10 @@ psql_completion(const char *text, int start, int end)
matches = complete_from_variables(text, ":", "", true);
}
+ /* If current word ends with a comma, add a space. */
+ if (ends_with(text, ','))
+ COMPLETE_WITH_CONST(text);
+
/* If no previous word, suggest one of the basic sql commands */
else if (previous_words_count == 0)
COMPLETE_WITH_LIST(sql_commands);
@@ -3457,7 +3498,9 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_CONST("IS");
/* SELECT */
- else if (TailMatches1("SELECT") || TailMatches2("SELECT", "ALL|DISTINCT"))
+ else if (HeadMatches1("SELECT|WITH") &&
+ CurrentQueryPartMatches("SELECT") &&
+ (ends_with(prev_wd, ',') || TailMatches1("SELECT|ALL|DISTINCT")))
COMPLETE_WITH_VERSIONED_SCHEMA_QUERY(Query_for_list_of_selectable_functions,
Query_addon_for_list_of_selectable_attributes);