pg.ddx.io pgsql-hackers@postgresql.org mailing list archive
help / color / mirror / Atom feed From: Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>
To: pavel.stehule@gmail.com
Cc: pgsql-hackers@postgresql.org
Subject: Re: IF (NOT) EXISTS in psql-completion
Date: Mon, 31 Oct 2016 10:15:48 +0900 (Tokyo Standard Time)
Message-ID: <20161031.101548.162143279.horiguchi.kyotaro@lab.ntt.co.jp> (raw )
In-Reply-To: <20160930.144303.91443471.horiguchi.kyotaro@lab.ntt.co.jp >
References: <CAFj8pRCpoYMoUzZ74p0JvX=orUxs7o88UR0z0-Lqt6W6bS9DaQ@mail.gmail.com >
<20160929.161600.224338668.horiguchi.kyotaro@lab.ntt.co.jp >
<20160930.144303.91443471.horiguchi.kyotaro@lab.ntt.co.jp >
List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
Hello,
At Fri, 30 Sep 2016 14:43:03 +0900 (Tokyo Standard Time), Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp> wrote in <20160930.144303.91443471.horiguchi.kyotaro@lab.ntt.co.jp >
> The following is the first part of the document I have written up
> to now. Please help me by giving me any corrections, suggestions,
> opinions, or anything else!
Anyway, I fixed space issues and addressed the
COMPLETE_WITH_QUERY()'s almost unused parameter problem. And
tried to write a README files.
Some incomplete suggestions are not of this patch and maybe
proposed as another patch.
regards,
--
Kyotaro Horiguchi
NTT Open Source Software Center
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
Attachments: download all (6 files, .tar.gz)
0001-Refactoring-tab-complete-to-make-psql_completion-cod.patch (text/x-patch, 122.6K) download
From 54f0ab6d145ccbfc9ebdf950b3d207e5a3cd15e6 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Wed, 14 Sep 2016 11:59:04 +0900
Subject: [PATCH 1/6] Refactoring tab-complete to make psql_completion code
simpler.
psql_completion consists of a long-long sequence of "else-if"s and
succeeding finishing code. This structure enforces us to use a very
tricky way to put something other than matching-completion pairs in
the midst of the sequence. This patch separates the
matching-completion pairs into individual function
"psql_completion_internal". Returning at the points of completion let
us free from the else-if sequence and let us put anything we want into
the matching-completion sequence.
Addition to that the amount of the code seems to be a good reason to
move it out of tab-complete.c. This patch searates it out as
tab-complete-macros.h
---
src/bin/psql/Makefile | 2 +
src/bin/psql/tab-complete-macros.h | 405 +++++++++++
src/bin/psql/tab-complete.c | 1347 ++++++++++++++----------------------
3 files changed, 932 insertions(+), 822 deletions(-)
create mode 100644 src/bin/psql/tab-complete-macros.h
diff --git a/src/bin/psql/Makefile b/src/bin/psql/Makefile
index 1f6a289..51f88ba 100644
--- a/src/bin/psql/Makefile
+++ b/src/bin/psql/Makefile
@@ -47,6 +47,8 @@ ifeq ($(GCC),yes)
psqlscanslash.o: CFLAGS += -Wno-error
endif
+tab-complete.o: tab-complete-macros.h
+
distprep: sql_help.h psqlscanslash.c
install: all installdirs
diff --git a/src/bin/psql/tab-complete-macros.h b/src/bin/psql/tab-complete-macros.h
new file mode 100644
index 0000000..8ee52b8
--- /dev/null
+++ b/src/bin/psql/tab-complete-macros.h
@@ -0,0 +1,405 @@
+/*
+ * psql - the PostgreSQL interactive terminal
+ *
+ * Copyright (c) 2000-2016, PostgreSQL Global Development Group
+ *
+ * src/bin/psql/tab-complete-macros.h
+ */
+#ifndef TAB_COMPLETE_MACROS_H
+#define TAB_COMPLETE_MACROS_H
+
+/*
+ * For compactness, we use these macros to reference previous_words[].
+ * Caution: do not access a previous_words[] entry without having checked
+ * previous_words_count to be sure it's valid. In most cases below, that
+ * check is implicit in a TailMatches() or similar macro, but in some places
+ * we have to check it explicitly.
+ */
+#define prev_wd (previous_words[0])
+#define prev2_wd (previous_words[1])
+#define prev3_wd (previous_words[2])
+#define prev4_wd (previous_words[3])
+#define prev5_wd (previous_words[4])
+#define prev6_wd (previous_words[5])
+#define prev7_wd (previous_words[6])
+#define prev8_wd (previous_words[7])
+#define prev9_wd (previous_words[8])
+
+/*
+ * Return the index in previous_words for index from the beginning. n is
+ * 1-based and the result is 0-based.
+ */
+#define HEAD_INDEX(n) \
+ (previous_words_count - (n))
+
+/*
+ * Macros for matching the last N words before point, and after head_sift,
+ * case-insensitively.
+ */
+#define TailMatches1(p1) \
+ (previous_words_count >= 1 && \
+ word_matches(p1, prev_wd))
+
+#define TailMatches2(p2, p1) \
+ (previous_words_count >= 2 && \
+ word_matches(p1, prev_wd) && \
+ word_matches(p2, prev2_wd))
+
+#define TailMatches3(p3, p2, p1) \
+ (previous_words_count >= 3 && \
+ word_matches(p1, prev_wd) && \
+ word_matches(p2, prev2_wd) && \
+ word_matches(p3, prev3_wd))
+
+#define TailMatches4(p4, p3, p2, p1) \
+ (previous_words_count >= 4 && \
+ word_matches(p1, prev_wd) && \
+ word_matches(p2, prev2_wd) && \
+ word_matches(p3, prev3_wd) && \
+ word_matches(p4, prev4_wd))
+
+#define TailMatches5(p5, p4, p3, p2, p1) \
+ (previous_words_count >= 5 && \
+ 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 TailMatches6(p6, p5, p4, p3, p2, p1) \
+ (previous_words_count >= 6 && \
+ 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 TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
+ (previous_words_count >= 7 && \
+ 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 TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
+ (previous_words_count >= 8 && \
+ 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 TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
+ (previous_words_count >= 9 && \
+ 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) && \
+ word_matches(p9, prev9_wd))
+
+ /*
+ * Macros for matching the last N words before point, and after
+ * head_shift, case-sensitively.
+ */
+#define TailMatchesCS1(p1) \
+ (previous_words_count >= 1 && \
+ word_matches_cs(p1, prev_wd))
+#define TailMatchesCS2(p2, p1) \
+ (previous_words_count >= 2 && \
+ word_matches_cs(p1, prev_wd) && \
+ word_matches_cs(p2, prev2_wd))
+
+ /*
+ * Macros for matching N words exactly to the line, and after head_shift,
+ * case-insensitively.
+ */
+#define Matches1(p1) \
+ (previous_words_count == 1 && \
+ TailMatches1(p1))
+#define Matches2(p1, p2) \
+ (previous_words_count == 2 && \
+ TailMatches2(p1, p2))
+#define Matches3(p1, p2, p3) \
+ (previous_words_count == 3 && \
+ TailMatches3(p1, p2, p3))
+#define Matches4(p1, p2, p3, p4) \
+ (previous_words_count == 4 && \
+ TailMatches4(p1, p2, p3, p4))
+#define Matches5(p1, p2, p3, p4, p5) \
+ (previous_words_count == 5 && \
+ TailMatches5(p1, p2, p3, p4, p5))
+#define Matches6(p1, p2, p3, p4, p5, p6) \
+ (previous_words_count == 6 && \
+ TailMatches6(p1, p2, p3, p4, p5, p6))
+#define Matches7(p1, p2, p3, p4, p5, p6, p7) \
+ (previous_words_count == 7 && \
+ TailMatches7(p1, p2, p3, p4, p5, p6, p7))
+#define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
+ (previous_words_count == 8 && \
+ TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
+#define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
+ (previous_words_count == 9 && \
+ TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
+
+/*
+ * Macros for matching N words after head_shift + sth in the line, regardless
+ * of what is after them, case-insensitively.
+ */
+#define MidMatches1(s, p1) \
+ (HEAD_INDEX(s) >=0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]))
+
+#define MidMatches2(s, p1, p2) \
+ (HEAD_INDEX((s) + 1) >= 0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]))
+
+#define MidMatches3(s, p1, p2, p3) \
+ (HEAD_INDEX((s) + 2) >= 0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
+ word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]))
+
+#define MidMatches4(s, p1, p2, p3, p4) \
+ (HEAD_INDEX((s) + 3) >= 0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
+ word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]) && \
+ word_matches(p4, previous_words[HEAD_INDEX((s) + 3)]))
+
+#define MidMatches5(s, p1, p2, p3, p4, p5) \
+ (HEAD_INDEX((s) + 4) >= 0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
+ word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]) && \
+ word_matches(p4, previous_words[HEAD_INDEX((s) + 3)]) && \
+ word_matches(p5, previous_words[HEAD_INDEX((s) + 4)]))
+
+#define MidMatches6(s,p1, p2, p3, p4, p5, p6) \
+ (HEAD_INDEX((s) + 5) >= 0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
+ word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]) && \
+ word_matches(p4, previous_words[HEAD_INDEX((s) + 3)]) && \
+ word_matches(p5, previous_words[HEAD_INDEX((s) + 4)]) && \
+ word_matches(p6, previous_words[HEAD_INDEX((s) + 5)]))
+
+#define MidMatches7(s,p1, p2, p3, p4, p5, p6, p7) \
+ (HEAD_INDEX((s) + 6) >= 0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
+ word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]) && \
+ word_matches(p4, previous_words[HEAD_INDEX((s) + 3)]) && \
+ word_matches(p5, previous_words[HEAD_INDEX((s) + 4)]) && \
+ word_matches(p6, previous_words[HEAD_INDEX((s) + 5)]) && \
+ word_matches(p7, previous_words[HEAD_INDEX((s) + 6)]))
+
+#define HeadMatches1(p1) \
+ MidMatches1(1, p1)
+#define HeadMatches2(p1, p2) \
+ MidMatches2(1, p1, p2)
+#define HeadMatches3(p1, p2, p3) \
+ MidMatches3(1, p1, p2, p3)
+#define HeadMatches4(p1, p2, p3, p4) \
+ MidMatches4(1, p1, p2, p3, p4)
+#define HeadMatches5(p1, p2, p3, p4, p5) \
+ MidMatches5(1, p1, p2, p3, p4, p5)
+#define HeadMatches6(p1, p2, p3, p4, p5, p6) \
+ MidMatches6(1, p1, p2, p3, p4, p5, p6)
+#define HeadMatches7(p1, p2, p3, p4, p5, p6, p7) \
+ MidMatches7(1, p1, p2, p3, p4, p5, p6, p7)
+
+/*
+ * A few macros to ease typing. You can use these to complete the given
+ * string with
+ * 1) The results from a query you pass it. (Perhaps one of those below?)
+ * 2) The results from a schema query you pass it.
+ * 3) The items from a null-pointer-terminated list (with or without
+ * case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
+ * 4) A string constant.
+ * 5) The list of attributes of the given table (possibly schema-qualified).
+ * 6) The list of arguments to the given function (possibly schema-qualified).
+ */
+#define COMPLETE_WITH_QUERY(query) \
+do { \
+ completion_charp = query; \
+ return completion_matches(text, complete_from_query); \
+} while (0)
+
+#define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
+do { \
+ completion_squery = &(query); \
+ completion_charp = addon; \
+ return completion_matches(text, complete_from_schema_query); \
+} while (0)
+
+#define COMPLETE_WITH_LIST_CS(list) \
+do { \
+ completion_charpp = list; \
+ completion_case_sensitive = true; \
+ return completion_matches(text, complete_from_list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST(list) \
+do { \
+ completion_charpp = list; \
+ completion_case_sensitive = false; \
+ return completion_matches(text, complete_from_list); \
+} while (0)
+
+#define COMPLETE_WITH_CONST(string) \
+do { \
+ completion_charp = string; \
+ completion_case_sensitive = false; \
+ return completion_matches(text, complete_from_const); \
+} while (0)
+
+#define COMPLETE_WITH_ATTR(relation, addon) \
+do { \
+ char *_completion_schema; \
+ char *_completion_table; \
+\
+ _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
+ false, false, pset.encoding); \
+ (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
+ false, false, pset.encoding); \
+ _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
+ false, false, pset.encoding); \
+ if (_completion_table == NULL) \
+ { \
+ completion_charp = Query_for_list_of_attributes addon; \
+ completion_info_charp = relation; \
+ } \
+ else \
+ { \
+ completion_charp = Query_for_list_of_attributes_with_schema addon; \
+ completion_info_charp = _completion_table; \
+ completion_info_charp2 = _completion_schema; \
+ } \
+ return completion_matches(text, complete_from_query); \
+} while (0)
+
+#define COMPLETE_WITH_FUNCTION_ARG(function) \
+do { \
+ char *_completion_schema; \
+ char *_completion_function; \
+\
+ _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
+ false, false, pset.encoding); \
+ (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
+ false, false, pset.encoding); \
+ _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
+ false, false, pset.encoding); \
+ if (_completion_function == NULL) \
+ { \
+ completion_charp = Query_for_list_of_arguments; \
+ completion_info_charp = function; \
+ } \
+ else \
+ { \
+ completion_charp = Query_for_list_of_arguments_with_schema; \
+ completion_info_charp = _completion_function; \
+ completion_info_charp2 = _completion_schema; \
+ } \
+ return completion_matches(text, complete_from_query); \
+} while (0)
+
+/*
+ * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
+ * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
+ */
+#define COMPLETE_WITH_LIST2(s1, s2) \
+do { \
+ static const char *const list[] = { s1, s2, NULL }; \
+ COMPLETE_WITH_LIST(list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST3(s1, s2, s3) \
+do { \
+ static const char *const list[] = { s1, s2, s3, NULL }; \
+ COMPLETE_WITH_LIST(list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
+do { \
+ static const char *const list[] = { s1, s2, s3, s4, NULL }; \
+ COMPLETE_WITH_LIST(list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
+do { \
+ static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
+ COMPLETE_WITH_LIST(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 }; \
+ COMPLETE_WITH_LIST(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 }; \
+ COMPLETE_WITH_LIST(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 }; \
+ COMPLETE_WITH_LIST(list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
+do { \
+ static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
+ COMPLETE_WITH_LIST(list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
+do { \
+ static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
+ COMPLETE_WITH_LIST(list); \
+} while (0)
+
+/*
+ * Likewise for COMPLETE_WITH_LIST_CS.
+ */
+#define COMPLETE_WITH_LIST_CS2(s1, s2) \
+do { \
+ static const char *const list[] = { s1, s2, NULL }; \
+ COMPLETE_WITH_LIST_CS(list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
+do { \
+ static const char *const list[] = { s1, s2, s3, NULL }; \
+ COMPLETE_WITH_LIST_CS(list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
+do { \
+ static const char *const list[] = { s1, s2, s3, s4, NULL }; \
+ COMPLETE_WITH_LIST_CS(list); \
+} while (0)
+
+#define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
+do { \
+ static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
+ COMPLETE_WITH_LIST_CS(list); \
+} while (0)
+
+
+
+#endif /* TAB_COMPLETE_MACROS_H */
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 50a45eb..679e58f 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -34,6 +34,7 @@
#include "postgres_fe.h"
#include "tab-complete.h"
+#include "tab-complete-macros.h"
#include "input.h"
/* If we don't have this, we might as well forget about the whole thing: */
@@ -133,186 +134,6 @@ static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */
static bool completion_case_sensitive; /* completion is case sensitive */
/*
- * A few macros to ease typing. You can use these to complete the given
- * string with
- * 1) The results from a query you pass it. (Perhaps one of those below?)
- * 2) The results from a schema query you pass it.
- * 3) The items from a null-pointer-terminated list (with or without
- * case-sensitive comparison; see also COMPLETE_WITH_LISTn, below).
- * 4) A string constant.
- * 5) The list of attributes of the given table (possibly schema-qualified).
- * 6/ The list of arguments to the given function (possibly schema-qualified).
- */
-#define COMPLETE_WITH_QUERY(query) \
-do { \
- completion_charp = query; \
- matches = completion_matches(text, complete_from_query); \
-} while (0)
-
-#define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
-do { \
- completion_squery = &(query); \
- completion_charp = addon; \
- matches = completion_matches(text, complete_from_schema_query); \
-} while (0)
-
-#define COMPLETE_WITH_LIST_CS(list) \
-do { \
- completion_charpp = list; \
- completion_case_sensitive = true; \
- matches = completion_matches(text, complete_from_list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST(list) \
-do { \
- completion_charpp = list; \
- completion_case_sensitive = false; \
- matches = completion_matches(text, complete_from_list); \
-} while (0)
-
-#define COMPLETE_WITH_CONST(string) \
-do { \
- completion_charp = string; \
- completion_case_sensitive = false; \
- matches = completion_matches(text, complete_from_const); \
-} while (0)
-
-#define COMPLETE_WITH_ATTR(relation, addon) \
-do { \
- char *_completion_schema; \
- char *_completion_table; \
-\
- _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \
- false, false, pset.encoding); \
- (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
- false, false, pset.encoding); \
- _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
- false, false, pset.encoding); \
- if (_completion_table == NULL) \
- { \
- completion_charp = Query_for_list_of_attributes addon; \
- completion_info_charp = relation; \
- } \
- else \
- { \
- completion_charp = Query_for_list_of_attributes_with_schema addon; \
- completion_info_charp = _completion_table; \
- completion_info_charp2 = _completion_schema; \
- } \
- matches = completion_matches(text, complete_from_query); \
-} while (0)
-
-#define COMPLETE_WITH_FUNCTION_ARG(function) \
-do { \
- char *_completion_schema; \
- char *_completion_function; \
-\
- _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \
- false, false, pset.encoding); \
- (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \
- false, false, pset.encoding); \
- _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \
- false, false, pset.encoding); \
- if (_completion_function == NULL) \
- { \
- completion_charp = Query_for_list_of_arguments; \
- completion_info_charp = function; \
- } \
- else \
- { \
- completion_charp = Query_for_list_of_arguments_with_schema; \
- completion_info_charp = _completion_function; \
- completion_info_charp2 = _completion_schema; \
- } \
- matches = completion_matches(text, complete_from_query); \
-} while (0)
-
-/*
- * These macros simplify use of COMPLETE_WITH_LIST for short, fixed lists.
- * There is no COMPLETE_WITH_LIST1; use COMPLETE_WITH_CONST for that case.
- */
-#define COMPLETE_WITH_LIST2(s1, s2) \
-do { \
- static const char *const list[] = { s1, s2, NULL }; \
- COMPLETE_WITH_LIST(list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST3(s1, s2, s3) \
-do { \
- static const char *const list[] = { s1, s2, s3, NULL }; \
- COMPLETE_WITH_LIST(list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST4(s1, s2, s3, s4) \
-do { \
- static const char *const list[] = { s1, s2, s3, s4, NULL }; \
- COMPLETE_WITH_LIST(list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST5(s1, s2, s3, s4, s5) \
-do { \
- static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
- COMPLETE_WITH_LIST(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 }; \
- COMPLETE_WITH_LIST(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 }; \
- COMPLETE_WITH_LIST(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 }; \
- COMPLETE_WITH_LIST(list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST9(s1, s2, s3, s4, s5, s6, s7, s8, s9) \
-do { \
- static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, NULL }; \
- COMPLETE_WITH_LIST(list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST10(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10) \
-do { \
- static const char *const list[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, NULL }; \
- COMPLETE_WITH_LIST(list); \
-} while (0)
-
-/*
- * Likewise for COMPLETE_WITH_LIST_CS.
- */
-#define COMPLETE_WITH_LIST_CS2(s1, s2) \
-do { \
- static const char *const list[] = { s1, s2, NULL }; \
- COMPLETE_WITH_LIST_CS(list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST_CS3(s1, s2, s3) \
-do { \
- static const char *const list[] = { s1, s2, s3, NULL }; \
- COMPLETE_WITH_LIST_CS(list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST_CS4(s1, s2, s3, s4) \
-do { \
- static const char *const list[] = { s1, s2, s3, s4, NULL }; \
- COMPLETE_WITH_LIST_CS(list); \
-} while (0)
-
-#define COMPLETE_WITH_LIST_CS5(s1, s2, s3, s4, s5) \
-do { \
- static const char *const list[] = { s1, s2, s3, s4, s5, NULL }; \
- COMPLETE_WITH_LIST_CS(list); \
-} while (0)
-
-/*
* Assembly instructions for schema queries
*/
@@ -962,6 +783,8 @@ static char **get_previous_words(int point, char **buffer, int *nwords);
static char *get_guctype(const char *varname);
+static char **psql_completion_internal(const char *text, char **previous_words,
+ int previous_words_count);
#ifdef NOT_USED
static char *quote_file_name(char *text, int match_type, char *quote_pointer);
static char *dequote_file_name(char *text, char quote_char);
@@ -1117,156 +940,58 @@ psql_completion(const char *text, int start, int end)
/* The number of words found on the input line. */
int previous_words_count;
- /*
- * For compactness, we use these macros to reference previous_words[].
- * Caution: do not access a previous_words[] entry without having checked
- * previous_words_count to be sure it's valid. In most cases below, that
- * check is implicit in a TailMatches() or similar macro, but in some
- * places we have to check it explicitly.
- */
-#define prev_wd (previous_words[0])
-#define prev2_wd (previous_words[1])
-#define prev3_wd (previous_words[2])
-#define prev4_wd (previous_words[3])
-#define prev5_wd (previous_words[4])
-#define prev6_wd (previous_words[5])
-#define prev7_wd (previous_words[6])
-#define prev8_wd (previous_words[7])
-#define prev9_wd (previous_words[8])
-
- /* Macros for matching the last N words before point, case-insensitively. */
-#define TailMatches1(p1) \
- (previous_words_count >= 1 && \
- word_matches(p1, prev_wd))
-
-#define TailMatches2(p2, p1) \
- (previous_words_count >= 2 && \
- word_matches(p1, prev_wd) && \
- word_matches(p2, prev2_wd))
-
-#define TailMatches3(p3, p2, p1) \
- (previous_words_count >= 3 && \
- word_matches(p1, prev_wd) && \
- word_matches(p2, prev2_wd) && \
- word_matches(p3, prev3_wd))
-
-#define TailMatches4(p4, p3, p2, p1) \
- (previous_words_count >= 4 && \
- word_matches(p1, prev_wd) && \
- word_matches(p2, prev2_wd) && \
- word_matches(p3, prev3_wd) && \
- word_matches(p4, prev4_wd))
-
-#define TailMatches5(p5, p4, p3, p2, p1) \
- (previous_words_count >= 5 && \
- 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 TailMatches6(p6, p5, p4, p3, p2, p1) \
- (previous_words_count >= 6 && \
- 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 TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
- (previous_words_count >= 7 && \
- 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 TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
- (previous_words_count >= 8 && \
- 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 TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
- (previous_words_count >= 9 && \
- 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) && \
- word_matches(p9, prev9_wd))
-
- /* Macros for matching the last N words before point, case-sensitively. */
-#define TailMatchesCS1(p1) \
- (previous_words_count >= 1 && \
- word_matches_cs(p1, prev_wd))
-#define TailMatchesCS2(p2, p1) \
- (previous_words_count >= 2 && \
- word_matches_cs(p1, prev_wd) && \
- word_matches_cs(p2, prev2_wd))
+ (void) end; /* "end" is not used */
- /*
- * Macros for matching N words beginning at the start of the line,
- * case-insensitively.
- */
-#define Matches1(p1) \
- (previous_words_count == 1 && \
- TailMatches1(p1))
-#define Matches2(p1, p2) \
- (previous_words_count == 2 && \
- TailMatches2(p1, p2))
-#define Matches3(p1, p2, p3) \
- (previous_words_count == 3 && \
- TailMatches3(p1, p2, p3))
-#define Matches4(p1, p2, p3, p4) \
- (previous_words_count == 4 && \
- TailMatches4(p1, p2, p3, p4))
-#define Matches5(p1, p2, p3, p4, p5) \
- (previous_words_count == 5 && \
- TailMatches5(p1, p2, p3, p4, p5))
-#define Matches6(p1, p2, p3, p4, p5, p6) \
- (previous_words_count == 6 && \
- TailMatches6(p1, p2, p3, p4, p5, p6))
-#define Matches7(p1, p2, p3, p4, p5, p6, p7) \
- (previous_words_count == 7 && \
- TailMatches7(p1, p2, p3, p4, p5, p6, p7))
-#define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
- (previous_words_count == 8 && \
- TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
-#define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
- (previous_words_count == 9 && \
- TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
+#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
+ rl_completion_append_character = ' ';
+#endif
+
+ /* Clear a few things. */
+ completion_charp = NULL;
+ completion_charpp = NULL;
+ completion_info_charp = NULL;
+ completion_info_charp2 = NULL;
/*
- * Macros for matching N words at the start of the line, regardless of
- * what is after them, case-insensitively.
+ * Scan the input line to extract the words before our current position.
+ * According to those we'll make some smart decisions on what the user is
+ * probably intending to type.
*/
-#define HeadMatches1(p1) \
- (previous_words_count >= 1 && \
- word_matches(p1, previous_words[previous_words_count - 1]))
+ previous_words = get_previous_words(start,
+ &words_buffer,
+ &previous_words_count);
+
+ matches = psql_completion_internal(text, previous_words,
+ previous_words_count);
-#define HeadMatches2(p1, p2) \
- (previous_words_count >= 2 && \
- word_matches(p1, previous_words[previous_words_count - 1]) && \
- word_matches(p2, previous_words[previous_words_count - 2]))
+ /* free storage */
+ free(previous_words);
+ free(words_buffer);
-#define HeadMatches3(p1, p2, p3) \
- (previous_words_count >= 3 && \
- word_matches(p1, previous_words[previous_words_count - 1]) && \
- word_matches(p2, previous_words[previous_words_count - 2]) && \
- word_matches(p3, previous_words[previous_words_count - 3]))
+ if (matches != NULL)
+ return matches;
+
+ /*
+ * If we still don't have anything to match we have to fabricate some sort
+ * of default list. If we were to just return NULL, readline automatically
+ * attempts filename completion, and that's usually no good.
+ */
+#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
+ rl_completion_append_character = '\0';
+#endif
+ COMPLETE_WITH_CONST(""); /* This returns matches */
+}
+/*
+ * The completion function.
+ *
+ * Makes completion list.
+ * Note: COMPLETE_WITH_* macros immediately return to the caller.
+ */
+static char **
+psql_completion_internal(const char *text, char **previous_words,
+ int previous_words_count)
+{
/* Known command-starting keywords. */
static const char *const sql_commands[] = {
"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
@@ -1298,90 +1023,80 @@ psql_completion(const char *text, int start, int end)
"\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL
};
- (void) end; /* "end" is not used */
-
-#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
- rl_completion_append_character = ' ';
-#endif
-
- /* Clear a few things. */
- completion_charp = NULL;
- completion_charpp = NULL;
- completion_info_charp = NULL;
- completion_info_charp2 = NULL;
-
- /*
- * Scan the input line to extract the words before our current position.
- * According to those we'll make some smart decisions on what the user is
- * probably intending to type.
- */
- previous_words = get_previous_words(start,
- &words_buffer,
- &previous_words_count);
-
/* If current word is a backslash command, offer completions for that */
if (text[0] == '\\')
COMPLETE_WITH_LIST_CS(backslash_commands);
/* If current word is a variable interpolation, handle that case */
- else if (text[0] == ':' && text[1] != ':')
+ if (text[0] == ':' && text[1] != ':')
{
if (text[1] == '\'')
- matches = complete_from_variables(text, ":'", "'", true);
- else if (text[1] == '"')
- matches = complete_from_variables(text, ":\"", "\"", true);
- else
- matches = complete_from_variables(text, ":", "", true);
+ return complete_from_variables(text, ":'", "'", true);
+ if (text[1] == '"')
+ return complete_from_variables(text, ":\"", "\"", true);
+
+ return complete_from_variables(text, ":", "", true);
}
/* If no previous word, suggest one of the basic sql commands */
- else if (previous_words_count == 0)
+ if (previous_words_count == 0)
COMPLETE_WITH_LIST(sql_commands);
/* CREATE */
/* complete with something you can create */
- else if (TailMatches1("CREATE"))
- matches = completion_matches(text, create_command_generator);
+ if (Matches1("CREATE"))
+ return completion_matches(text, create_command_generator);
/* DROP, but not DROP embedded in other commands */
/* complete with something you can drop */
- else if (Matches1("DROP"))
- matches = completion_matches(text, drop_command_generator);
+ if (Matches1("DROP"))
+ return completion_matches(text, drop_command_generator);
/* ALTER */
/* ALTER TABLE */
- else if (Matches2("ALTER", "TABLE"))
+ if (Matches2("ALTER", "TABLE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
"UNION SELECT 'ALL IN TABLESPACE'");
/* ALTER something */
- else if (Matches1("ALTER"))
+ if (Matches1("ALTER"))
{
static const char *const list_ALTER[] =
- {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
- "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
- "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR",
- "POLICY", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM", "TABLE",
- "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
- "USER", "USER MAPPING FOR", "VIEW", NULL};
+ {"AGGREGATE",
+ "COLLATION", "CONVERSION",
+ "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
+ "EVENT TRIGGER", "EXTENSION",
+ "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
+ "GROUP",
+ "INDEX",
+ "LANGUAGE", "LARGE OBJECT",
+ "MATERIALIZED VIEW",
+ "OPERATOR",
+ "POLICY",
+ "ROLE", "RULE",
+ "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM",
+ "TABLE", "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
+ "USER", "USER MAPPING FOR",
+ "VIEW",
+ NULL};
COMPLETE_WITH_LIST(list_ALTER);
}
/* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */
- else if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
+ if (TailMatches4("ALL", "IN", "TABLESPACE", MatchAny))
COMPLETE_WITH_LIST2("SET TABLESPACE", "OWNED BY");
/* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */
- else if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
+ if (TailMatches6("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
/* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */
- else if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
+ if (TailMatches7("ALL", "IN", "TABLESPACE", MatchAny, "OWNED", "BY", MatchAny))
COMPLETE_WITH_CONST("SET TABLESPACE");
/* ALTER AGGREGATE,FUNCTION <name> */
- else if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
+ if (Matches3("ALTER", "AGGREGATE|FUNCTION", MatchAny))
COMPLETE_WITH_CONST("(");
/* ALTER AGGREGATE,FUNCTION <name> (...) */
- else if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
+ if (Matches4("ALTER", "AGGREGATE|FUNCTION", MatchAny, MatchAny))
{
if (ends_with(prev_wd, ')'))
COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
@@ -1390,63 +1105,63 @@ psql_completion(const char *text, int start, int end)
}
/* ALTER SCHEMA <name> */
- else if (Matches3("ALTER", "SCHEMA", MatchAny))
+ if (Matches3("ALTER", "SCHEMA", MatchAny))
COMPLETE_WITH_LIST2("OWNER TO", "RENAME TO");
/* ALTER COLLATION <name> */
- else if (Matches3("ALTER", "COLLATION", MatchAny))
+ if (Matches3("ALTER", "COLLATION", MatchAny))
COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER CONVERSION <name> */
- else if (Matches3("ALTER", "CONVERSION", MatchAny))
+ if (Matches3("ALTER", "CONVERSION", MatchAny))
COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
/* ALTER DATABASE <name> */
- else if (Matches3("ALTER", "DATABASE", MatchAny))
+ if (Matches3("ALTER", "DATABASE", MatchAny))
COMPLETE_WITH_LIST7("RESET", "SET", "OWNER TO", "RENAME TO",
"IS_TEMPLATE", "ALLOW_CONNECTIONS",
"CONNECTION LIMIT");
/* ALTER EVENT TRIGGER */
- else if (Matches3("ALTER", "EVENT", "TRIGGER"))
+ if (Matches3("ALTER", "EVENT", "TRIGGER"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
/* ALTER EVENT TRIGGER <name> */
- else if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
+ if (Matches4("ALTER", "EVENT", "TRIGGER", MatchAny))
COMPLETE_WITH_LIST4("DISABLE", "ENABLE", "OWNER TO", "RENAME TO");
/* ALTER EVENT TRIGGER <name> ENABLE */
- else if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
+ if (Matches5("ALTER", "EVENT", "TRIGGER", MatchAny, "ENABLE"))
COMPLETE_WITH_LIST2("REPLICA", "ALWAYS");
/* ALTER EXTENSION <name> */
- else if (Matches3("ALTER", "EXTENSION", MatchAny))
+ if (Matches3("ALTER", "EXTENSION", MatchAny))
COMPLETE_WITH_LIST4("ADD", "DROP", "UPDATE", "SET SCHEMA");
/* ALTER EXTENSION <name> UPDATE */
- else if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
+ if (Matches4("ALTER", "EXTENSION", MatchAny, "UPDATE"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions_with_TO);
}
/* ALTER EXTENSION <name> UPDATE TO */
- else if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
+ if (Matches5("ALTER", "EXTENSION", MatchAny, "UPDATE", "TO"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
}
/* ALTER FOREIGN */
- else if (Matches2("ALTER", "FOREIGN"))
+ if (Matches2("ALTER", "FOREIGN"))
COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
/* ALTER FOREIGN DATA WRAPPER <name> */
- else if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
+ if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
/* ALTER FOREIGN TABLE <name> */
- else if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
+ if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
{
static const char *const list_ALTER_FOREIGN_TABLE[] =
{"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT",
@@ -1457,42 +1172,42 @@ psql_completion(const char *text, int start, int end)
}
/* ALTER INDEX */
- else if (Matches2("ALTER", "INDEX"))
+ if (Matches2("ALTER", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
"UNION SELECT 'ALL IN TABLESPACE'");
/* ALTER INDEX <name> */
- else if (Matches3("ALTER", "INDEX", MatchAny))
+ if (Matches3("ALTER", "INDEX", MatchAny))
COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
/* ALTER INDEX <name> SET */
- else if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
+ if (Matches4("ALTER", "INDEX", MatchAny, "SET"))
COMPLETE_WITH_LIST2("(", "TABLESPACE");
/* ALTER INDEX <name> RESET */
- else if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
+ if (Matches4("ALTER", "INDEX", MatchAny, "RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER INDEX <foo> SET|RESET ( */
- else if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
+ if (Matches5("ALTER", "INDEX", MatchAny, "RESET", "("))
COMPLETE_WITH_LIST3("fillfactor", "fastupdate",
"gin_pending_list_limit");
- else if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
+ if (Matches5("ALTER", "INDEX", MatchAny, "SET", "("))
COMPLETE_WITH_LIST3("fillfactor =", "fastupdate =",
"gin_pending_list_limit =");
/* ALTER LANGUAGE <name> */
- else if (Matches3("ALTER", "LANGUAGE", MatchAny))
+ if (Matches3("ALTER", "LANGUAGE", MatchAny))
COMPLETE_WITH_LIST2("OWNER_TO", "RENAME TO");
/* ALTER LARGE OBJECT <oid> */
- else if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
+ if (Matches4("ALTER", "LARGE", "OBJECT", MatchAny))
COMPLETE_WITH_CONST("OWNER TO");
/* ALTER MATERIALIZED VIEW */
- else if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
+ 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 (Matches3("ALTER", "USER|ROLE", MatchAny) &&
- !TailMatches2("USER", "MAPPING"))
+ if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
+ !TailMatches2("USER", "MAPPING"))
{
static const char *const list_ALTERUSER[] =
{"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
@@ -1506,7 +1221,7 @@ psql_completion(const char *text, int start, int end)
}
/* ALTER USER,ROLE <name> WITH */
- else if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
+ if (Matches4("ALTER", "USER|ROLE", MatchAny, "WITH"))
{
/* Similar to the above, but don't complete "WITH" again. */
static const char *const list_ALTERUSER_WITH[] =
@@ -1521,43 +1236,43 @@ psql_completion(const char *text, int start, int end)
}
/* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
- else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
+ if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
COMPLETE_WITH_CONST("PASSWORD");
/* ALTER DEFAULT PRIVILEGES */
- else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
+ if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
COMPLETE_WITH_LIST3("FOR ROLE", "FOR USER", "IN SCHEMA");
/* ALTER DEFAULT PRIVILEGES FOR */
- else if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
+ if (Matches4("ALTER", "DEFAULT", "PRIVILEGES", "FOR"))
COMPLETE_WITH_LIST2("ROLE", "USER");
/* ALTER DEFAULT PRIVILEGES { FOR ROLE ... | IN SCHEMA ... } */
- else if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER", MatchAny) ||
+ if (Matches6("ALTER", "DEFAULT", "PRIVILEGES", "FOR", "ROLE|USER", MatchAny) ||
Matches6("ALTER", "DEFAULT", "PRIVILEGES", "IN", "SCHEMA", MatchAny))
COMPLETE_WITH_LIST2("GRANT", "REVOKE");
/* ALTER DOMAIN <name> */
- else if (Matches3("ALTER", "DOMAIN", MatchAny))
+ if (Matches3("ALTER", "DOMAIN", MatchAny))
COMPLETE_WITH_LIST6("ADD", "DROP", "OWNER TO", "RENAME", "SET",
"VALIDATE CONSTRAINT");
/* ALTER DOMAIN <sth> DROP */
- else if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
+ if (Matches4("ALTER", "DOMAIN", MatchAny, "DROP"))
COMPLETE_WITH_LIST3("CONSTRAINT", "DEFAULT", "NOT NULL");
/* ALTER DOMAIN <sth> DROP|RENAME|VALIDATE CONSTRAINT */
- else if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
+ if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
}
/* ALTER DOMAIN <sth> RENAME */
- else if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
+ if (Matches4("ALTER", "DOMAIN", MatchAny, "RENAME"))
COMPLETE_WITH_LIST2("CONSTRAINT", "TO");
/* ALTER DOMAIN <sth> RENAME CONSTRAINT <sth> */
- else if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
+ if (Matches6("ALTER", "DOMAIN", MatchAny, "RENAME", "CONSTRAINT", MatchAny))
COMPLETE_WITH_CONST("TO");
/* ALTER DOMAIN <sth> SET */
- else if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
+ if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
/* ALTER SEQUENCE <name> */
- else if (Matches3("ALTER", "SEQUENCE", MatchAny))
+ if (Matches3("ALTER", "SEQUENCE", MatchAny))
{
static const char *const list_ALTERSEQUENCE[] =
{"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE",
@@ -1566,74 +1281,74 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_ALTERSEQUENCE);
}
/* ALTER SEQUENCE <name> NO */
- else if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
+ if (Matches4("ALTER", "SEQUENCE", MatchAny, "NO"))
COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
/* ALTER SERVER <name> */
- else if (Matches3("ALTER", "SERVER", MatchAny))
+ if (Matches3("ALTER", "SERVER", MatchAny))
COMPLETE_WITH_LIST4("VERSION", "OPTIONS", "OWNER TO", "RENAME TO");
/* ALTER SERVER <name> VERSION <version> */
- else if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
+ if (Matches5("ALTER", "SERVER", MatchAny, "VERSION", MatchAny))
COMPLETE_WITH_CONST("OPTIONS");
/* ALTER SYSTEM SET, RESET, RESET ALL */
- else if (Matches2("ALTER", "SYSTEM"))
+ if (Matches2("ALTER", "SYSTEM"))
COMPLETE_WITH_LIST2("SET", "RESET");
/* ALTER SYSTEM SET|RESET <name> */
- else if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
+ if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
/* ALTER VIEW <name> */
- else if (Matches3("ALTER", "VIEW", MatchAny))
+ if (Matches3("ALTER", "VIEW", MatchAny))
COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
"SET SCHEMA");
/* ALTER MATERIALIZED VIEW <name> */
- else if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
+ if (Matches4("ALTER", "MATERIALIZED", "VIEW", MatchAny))
COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
"SET SCHEMA");
/* ALTER POLICY <name> */
- else if (Matches2("ALTER", "POLICY"))
+ if (Matches2("ALTER", "POLICY"))
COMPLETE_WITH_QUERY(Query_for_list_of_policies);
/* ALTER POLICY <name> ON */
- else if (Matches3("ALTER", "POLICY", MatchAny))
+ if (Matches3("ALTER", "POLICY", MatchAny))
COMPLETE_WITH_CONST("ON");
/* ALTER POLICY <name> ON <table> */
- else if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
+ if (Matches4("ALTER", "POLICY", MatchAny, "ON"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
}
/* ALTER POLICY <name> ON <table> - show options */
- else if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
+ if (Matches5("ALTER", "POLICY", MatchAny, "ON", MatchAny))
COMPLETE_WITH_LIST4("RENAME TO", "TO", "USING (", "WITH CHECK (");
/* ALTER POLICY <name> ON <table> TO <role> */
- else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
+ if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
/* ALTER POLICY <name> ON <table> USING ( */
- else if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
+ if (Matches6("ALTER", "POLICY", MatchAny, "ON", MatchAny, "USING"))
COMPLETE_WITH_CONST("(");
/* ALTER POLICY <name> ON <table> WITH CHECK ( */
- else if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
+ if (Matches7("ALTER", "POLICY", MatchAny, "ON", MatchAny, "WITH", "CHECK"))
COMPLETE_WITH_CONST("(");
/* ALTER RULE <name>, add ON */
- else if (Matches3("ALTER", "RULE", MatchAny))
+ if (Matches3("ALTER", "RULE", MatchAny))
COMPLETE_WITH_CONST("ON");
/* If we have ALTER RULE <name> ON, then add the correct tablename */
- else if (Matches4("ALTER", "RULE", MatchAny, "ON"))
+ if (Matches4("ALTER", "RULE", MatchAny, "ON"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
}
/* ALTER RULE <name> ON <name> */
- else if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
+ if (Matches5("ALTER", "RULE", MatchAny, "ON", MatchAny))
COMPLETE_WITH_CONST("RENAME TO");
/* ALTER TRIGGER <name>, add ON */
- else if (Matches3("ALTER", "TRIGGER", MatchAny))
+ if (Matches3("ALTER", "TRIGGER", MatchAny))
COMPLETE_WITH_CONST("ON");
- else if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
+ if (Matches4("ALTER", "TRIGGER", MatchAny, MatchAny))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
@@ -1642,17 +1357,17 @@ psql_completion(const char *text, int start, int end)
/*
* If we have ALTER TRIGGER <sth> ON, then add the correct tablename
*/
- else if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
+ if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* ALTER TRIGGER <name> ON <name> */
- else if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
+ if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
COMPLETE_WITH_CONST("RENAME TO");
/*
* If we detect ALTER TABLE <name>, suggest sub commands
*/
- else if (Matches3("ALTER", "TABLE", MatchAny))
+ if (Matches3("ALTER", "TABLE", MatchAny))
{
static const char *const list_ALTER2[] =
{"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT",
@@ -1662,114 +1377,114 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_ALTER2);
}
/* ALTER TABLE xxx ENABLE */
- else if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "ENABLE"))
COMPLETE_WITH_LIST5("ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE",
"TRIGGER");
- else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "REPLICA|ALWAYS"))
COMPLETE_WITH_LIST2("RULE", "TRIGGER");
- else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "RULE"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_rule_of_table);
}
- else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
+ if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "RULE"))
{
completion_info_charp = prev4_wd;
COMPLETE_WITH_QUERY(Query_for_rule_of_table);
}
- else if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "ENABLE", "TRIGGER"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
}
- else if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
+ if (Matches6("ALTER", "TABLE", MatchAny, "ENABLE", MatchAny, "TRIGGER"))
{
completion_info_charp = prev4_wd;
COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
}
/* ALTER TABLE xxx INHERIT */
- else if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
/* ALTER TABLE xxx NO INHERIT */
- else if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
/* ALTER TABLE xxx DISABLE */
- else if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
- else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "RULE"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_rule_of_table);
}
- else if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "DISABLE", "TRIGGER"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
}
/* ALTER TABLE xxx ALTER */
- else if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
/* ALTER TABLE xxx RENAME */
- else if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
- else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
COMPLETE_WITH_ATTR(prev3_wd, "");
/* ALTER TABLE xxx RENAME yyy */
- else if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
+ if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
COMPLETE_WITH_CONST("TO");
/* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */
- else if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
+ if (Matches6("ALTER", "TABLE", MatchAny, "RENAME", "COLUMN|CONSTRAINT", MatchAnyExcept("TO")))
COMPLETE_WITH_CONST("TO");
/* If we have ALTER TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
- else if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "DROP"))
COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
/* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
- else if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
COMPLETE_WITH_ATTR(prev3_wd, "");
/*
* If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
* provide list of constraints
*/
- else if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "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 (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
+ if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
/* ALTER TABLE ALTER [COLUMN] <foo> SET */
- else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
+ if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
/* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
- else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
+ if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
/* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
- else if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
+ if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
/* ALTER TABLE ALTER [COLUMN] <foo> DROP */
- else if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
+ if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
Matches8("ALTER", "TABLE", MatchAny, "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
- else if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
COMPLETE_WITH_CONST("ON");
- else if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
{
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_index_of_table);
}
/* If we have ALTER TABLE <sth> SET, provide list of attributes and '(' */
- else if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "SET"))
COMPLETE_WITH_LIST7("(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED",
"WITH", "WITHOUT");
@@ -1777,19 +1492,19 @@ psql_completion(const char *text, int start, int end)
* If we have ALTER TABLE <sth> SET TABLESPACE provide a list of
* tablespaces
*/
- else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "SET", "TABLESPACE"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
/* If we have ALTER TABLE <sth> SET WITH provide OIDS */
- else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITH"))
COMPLETE_WITH_CONST("OIDS");
/* If we have ALTER TABLE <sth> SET WITHOUT provide CLUSTER or OIDS */
- else if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "SET", "WITHOUT"))
COMPLETE_WITH_LIST2("CLUSTER", "OIDS");
/* ALTER TABLE <foo> RESET */
- else if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER TABLE <foo> SET|RESET ( */
- else if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
+ if (Matches5("ALTER", "TABLE", MatchAny, "SET|RESET", "("))
{
static const char *const list_TABLEOPTIONS[] =
{
@@ -1827,103 +1542,103 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_TABLEOPTIONS);
}
- else if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
+ if (Matches7("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING", "INDEX"))
{
completion_info_charp = prev5_wd;
COMPLETE_WITH_QUERY(Query_for_index_of_table);
}
- else if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
+ if (Matches6("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY", "USING"))
COMPLETE_WITH_CONST("INDEX");
- else if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
+ if (Matches5("ALTER", "TABLE", MatchAny, "REPLICA", "IDENTITY"))
COMPLETE_WITH_LIST4("FULL", "NOTHING", "DEFAULT", "USING");
- else if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
+ if (Matches4("ALTER", "TABLE", MatchAny, "REPLICA"))
COMPLETE_WITH_CONST("IDENTITY");
/* ALTER TABLESPACE <foo> with RENAME TO, OWNER TO, SET, RESET */
- else if (Matches3("ALTER", "TABLESPACE", MatchAny))
+ if (Matches3("ALTER", "TABLESPACE", MatchAny))
COMPLETE_WITH_LIST4("RENAME TO", "OWNER TO", "SET", "RESET");
/* ALTER TABLESPACE <foo> SET|RESET */
- else if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
+ if (Matches4("ALTER", "TABLESPACE", MatchAny, "SET|RESET"))
COMPLETE_WITH_CONST("(");
/* ALTER TABLESPACE <foo> SET|RESET ( */
- else if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
+ if (Matches5("ALTER", "TABLESPACE", MatchAny, "SET|RESET", "("))
COMPLETE_WITH_LIST3("seq_page_cost", "random_page_cost",
"effective_io_concurrency");
/* ALTER TEXT SEARCH */
- else if (Matches3("ALTER", "TEXT", "SEARCH"))
+ if (Matches3("ALTER", "TEXT", "SEARCH"))
COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
- else if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
+ if (Matches5("ALTER", "TEXT", "SEARCH", "TEMPLATE|PARSER", MatchAny))
COMPLETE_WITH_LIST2("RENAME TO", "SET SCHEMA");
- else if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
+ if (Matches5("ALTER", "TEXT", "SEARCH", "DICTIONARY", MatchAny))
COMPLETE_WITH_LIST3("OWNER TO", "RENAME TO", "SET SCHEMA");
- else if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
+ if (Matches5("ALTER", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
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 (Matches3("ALTER", "TYPE", MatchAny))
+ if (Matches3("ALTER", "TYPE", MatchAny))
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 (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
+ if (Matches4("ALTER", "TYPE", MatchAny, "ADD"))
COMPLETE_WITH_LIST2("ATTRIBUTE", "VALUE");
/* ALTER TYPE <foo> RENAME */
- else if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
+ if (Matches4("ALTER", "TYPE", MatchAny, "RENAME"))
COMPLETE_WITH_LIST2("ATTRIBUTE", "TO");
/* ALTER TYPE xxx RENAME ATTRIBUTE yyy */
- else if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny))
+ if (Matches6("ALTER", "TYPE", MatchAny, "RENAME", "ATTRIBUTE", MatchAny))
COMPLETE_WITH_CONST("TO");
/*
* If we have ALTER TYPE <sth> ALTER/DROP/RENAME ATTRIBUTE, provide list
* of attributes
*/
- else if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
+ if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
COMPLETE_WITH_ATTR(prev3_wd, "");
/* ALTER TYPE ALTER ATTRIBUTE <foo> */
- else if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
+ if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
COMPLETE_WITH_CONST("TYPE");
/* complete ALTER GROUP <foo> */
- else if (Matches3("ALTER", "GROUP", MatchAny))
+ if (Matches3("ALTER", "GROUP", MatchAny))
COMPLETE_WITH_LIST3("ADD USER", "DROP USER", "RENAME TO");
/* complete ALTER GROUP <foo> ADD|DROP with USER */
- else if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
+ if (Matches4("ALTER", "GROUP", MatchAny, "ADD|DROP"))
COMPLETE_WITH_CONST("USER");
/* complete ALTER GROUP <foo> ADD|DROP USER with a user name */
- else if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
+ if (Matches5("ALTER", "GROUP", MatchAny, "ADD|DROP", "USER"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
/* BEGIN */
- else if (Matches1("BEGIN"))
+ if (Matches1("BEGIN"))
COMPLETE_WITH_LIST6("WORK", "TRANSACTION", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
/* END, ABORT */
- else if (Matches1("END|ABORT"))
+ if (Matches1("END|ABORT"))
COMPLETE_WITH_LIST2("WORK", "TRANSACTION");
/* COMMIT */
- else if (Matches1("COMMIT"))
+ if (Matches1("COMMIT"))
COMPLETE_WITH_LIST3("WORK", "TRANSACTION", "PREPARED");
/* RELEASE SAVEPOINT */
- else if (Matches1("RELEASE"))
+ if (Matches1("RELEASE"))
COMPLETE_WITH_CONST("SAVEPOINT");
/* ROLLBACK */
- else if (Matches1("ROLLBACK"))
+ if (Matches1("ROLLBACK"))
COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
/* CLUSTER */
- else if (Matches1("CLUSTER"))
+ if (Matches1("CLUSTER"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
- else if (Matches2("CLUSTER", "VERBOSE"))
+ if (Matches2("CLUSTER", "VERBOSE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
/* If we have CLUSTER <sth>, then add "USING" */
- else if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
+ if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
COMPLETE_WITH_CONST("USING");
/* If we have CLUSTER VERBOSE <sth>, then add "USING" */
- else if (Matches3("CLUSTER", "VERBOSE", MatchAny))
+ if (Matches3("CLUSTER", "VERBOSE", MatchAny))
COMPLETE_WITH_CONST("USING");
/* If we have CLUSTER <sth> USING, then add the index as well */
- else if (Matches3("CLUSTER", MatchAny, "USING") ||
+ if (Matches3("CLUSTER", MatchAny, "USING") ||
Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
{
completion_info_charp = prev2_wd;
@@ -1931,9 +1646,9 @@ psql_completion(const char *text, int start, int end)
}
/* COMMENT */
- else if (Matches1("COMMENT"))
+ if (Matches1("COMMENT"))
COMPLETE_WITH_CONST("ON");
- else if (Matches2("COMMENT", "ON"))
+ if (Matches2("COMMENT", "ON"))
{
static const char *const list_COMMENT[] =
{"ACCESS METHOD", "CAST", "COLLATION", "CONVERSION", "DATABASE",
@@ -1946,26 +1661,26 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_COMMENT);
}
- else if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
+ if (Matches4("COMMENT", "ON", "ACCESS", "METHOD"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
- else if (Matches3("COMMENT", "ON", "FOREIGN"))
+ if (Matches3("COMMENT", "ON", "FOREIGN"))
COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
- else if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
+ if (Matches4("COMMENT", "ON", "TEXT", "SEARCH"))
COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
- else if (Matches3("COMMENT", "ON", "CONSTRAINT"))
+ if (Matches3("COMMENT", "ON", "CONSTRAINT"))
COMPLETE_WITH_QUERY(Query_for_all_table_constraints);
- else if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
+ if (Matches4("COMMENT", "ON", "CONSTRAINT", MatchAny))
COMPLETE_WITH_CONST("ON");
- else if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
+ if (Matches5("COMMENT", "ON", "CONSTRAINT", MatchAny, "ON"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
}
- else if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
+ if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
- else if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
+ if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
- else if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
+ if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
COMPLETE_WITH_CONST("IS");
@@ -1976,97 +1691,97 @@ psql_completion(const char *text, int start, int end)
* If we have COPY, offer list of tables or "(" (Also cover the analogous
* backslash command).
*/
- else if (Matches1("COPY|\\copy"))
+ if (Matches1("COPY|\\copy"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
" UNION ALL SELECT '('");
/* If we have COPY BINARY, complete with list of tables */
- else if (Matches2("COPY", "BINARY"))
+ if (Matches2("COPY", "BINARY"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* If we have COPY (, complete it with legal commands */
- else if (Matches2("COPY|\\copy", "("))
+ if (Matches2("COPY|\\copy", "("))
COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
/* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
- else if (Matches2("COPY|\\copy", MatchAny) ||
+ if (Matches2("COPY|\\copy", MatchAny) ||
Matches3("COPY", "BINARY", MatchAny))
COMPLETE_WITH_LIST2("FROM", "TO");
/* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
- else if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
+ if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
{
completion_charp = "";
- matches = completion_matches(text, complete_from_files);
+ return completion_matches(text, complete_from_files);
}
/* Handle COPY [BINARY] <sth> FROM|TO filename */
- else if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
+ if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
"ENCODING");
/* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
- else if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
+ if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
"FORCE NOT NULL");
/* CREATE ACCESS METHOD */
/* Complete "CREATE ACCESS METHOD <name>" */
- else if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
+ if (Matches4("CREATE", "ACCESS", "METHOD", MatchAny))
COMPLETE_WITH_CONST("TYPE");
/* Complete "CREATE ACCESS METHOD <name> TYPE" */
- else if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
+ if (Matches5("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE"))
COMPLETE_WITH_CONST("INDEX");
/* Complete "CREATE ACCESS METHOD <name> TYPE <type>" */
- else if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
+ if (Matches6("CREATE", "ACCESS", "METHOD", MatchAny, "TYPE", MatchAny))
COMPLETE_WITH_CONST("HANDLER");
/* CREATE DATABASE */
- else if (Matches3("CREATE", "DATABASE", MatchAny))
+ if (Matches3("CREATE", "DATABASE", MatchAny))
COMPLETE_WITH_LIST9("OWNER", "TEMPLATE", "ENCODING", "TABLESPACE",
"IS_TEMPLATE",
"ALLOW_CONNECTIONS", "CONNECTION LIMIT",
"LC_COLLATE", "LC_CTYPE");
- else if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
+ if (Matches4("CREATE", "DATABASE", MatchAny, "TEMPLATE"))
COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
/* CREATE EXTENSION */
/* Complete with available extensions rather than installed ones. */
- else if (Matches2("CREATE", "EXTENSION"))
+ if (Matches2("CREATE", "EXTENSION"))
COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
/* CREATE EXTENSION <name> */
- else if (Matches3("CREATE", "EXTENSION", MatchAny))
+ if (Matches3("CREATE", "EXTENSION", MatchAny))
COMPLETE_WITH_LIST3("WITH SCHEMA", "CASCADE", "VERSION");
/* CREATE EXTENSION <name> VERSION */
- else if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
+ if (Matches4("CREATE", "EXTENSION", MatchAny, "VERSION"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_available_extension_versions);
}
/* CREATE FOREIGN */
- else if (Matches2("CREATE", "FOREIGN"))
+ if (Matches2("CREATE", "FOREIGN"))
COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
/* CREATE FOREIGN DATA WRAPPER */
- else if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
+ if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
/* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
/* First off we complete CREATE UNIQUE with "INDEX" */
- else if (TailMatches2("CREATE", "UNIQUE"))
+ if (TailMatches2("CREATE", "UNIQUE"))
COMPLETE_WITH_CONST("INDEX");
/*
* If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
* existing indexes
*/
- else if (TailMatches2("CREATE|UNIQUE", "INDEX"))
+ if (TailMatches2("CREATE|UNIQUE", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
" UNION SELECT 'ON'"
" UNION SELECT 'CONCURRENTLY'");
/* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
- else if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
+ if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
TailMatches2("INDEX|CONCURRENTLY", "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
@@ -2074,11 +1789,11 @@ psql_completion(const char *text, int start, int end)
* Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
* indexes
*/
- else if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
+ if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
" UNION SELECT 'ON'");
/* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
- else if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
+ if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
COMPLETE_WITH_CONST("ON");
@@ -2086,117 +1801,117 @@ psql_completion(const char *text, int start, int end)
* Complete INDEX <name> ON <table> with a list of table columns (which
* should really be in parens)
*/
- else if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
- TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
+ if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
+ TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
COMPLETE_WITH_LIST2("(", "USING");
- else if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
- TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
+ if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
+ TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
COMPLETE_WITH_ATTR(prev2_wd, "");
/* same if you put in USING */
- else if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
+ if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
COMPLETE_WITH_ATTR(prev4_wd, "");
/* Complete USING with an index method */
- else if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
+ if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
TailMatches4("INDEX", "ON", MatchAny, "USING"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
- else if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
+ if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
!TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
!TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
COMPLETE_WITH_CONST("(");
/* CREATE POLICY */
/* Complete "CREATE POLICY <name> ON" */
- else if (Matches3("CREATE", "POLICY", MatchAny))
+ if (Matches3("CREATE", "POLICY", MatchAny))
COMPLETE_WITH_CONST("ON");
/* Complete "CREATE POLICY <name> ON <table>" */
- else if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
+ if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* Complete "CREATE POLICY <name> ON <table> FOR|TO|USING|WITH CHECK" */
- else if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
+ if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
COMPLETE_WITH_LIST4("FOR", "TO", "USING (", "WITH CHECK (");
/* CREATE POLICY <name> ON <table> FOR ALL|SELECT|INSERT|UPDATE|DELETE */
- else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
+ if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR"))
COMPLETE_WITH_LIST5("ALL", "SELECT", "INSERT", "UPDATE", "DELETE");
/* Complete "CREATE POLICY <name> ON <table> FOR INSERT TO|WITH CHECK" */
- else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
+ if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "INSERT"))
COMPLETE_WITH_LIST2("TO", "WITH CHECK (");
/* Complete "CREATE POLICY <name> ON <table> FOR SELECT|DELETE TO|USING" */
- else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
+ if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "SELECT|DELETE"))
COMPLETE_WITH_LIST2("TO", "USING (");
/* CREATE POLICY <name> ON <table> FOR ALL|UPDATE TO|USING|WITH CHECK */
- else if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
+ if (Matches7("CREATE", "POLICY", MatchAny, "ON", MatchAny, "FOR", "ALL|UPDATE"))
COMPLETE_WITH_LIST3("TO", "USING (", "WITH CHECK (");
/* Complete "CREATE POLICY <name> ON <table> TO <role>" */
- else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
+ if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
/* Complete "CREATE POLICY <name> ON <table> USING (" */
- else if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
+ if (Matches6("CREATE", "POLICY", MatchAny, "ON", MatchAny, "USING"))
COMPLETE_WITH_CONST("(");
/* CREATE RULE */
/* Complete "CREATE RULE <sth>" with "AS ON" */
- else if (Matches3("CREATE", "RULE", MatchAny))
+ if (Matches3("CREATE", "RULE", MatchAny))
COMPLETE_WITH_CONST("AS ON");
/* Complete "CREATE RULE <sth> AS" with "ON" */
- else if (Matches4("CREATE", "RULE", MatchAny, "AS"))
+ if (Matches4("CREATE", "RULE", MatchAny, "AS"))
COMPLETE_WITH_CONST("ON");
/* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
- else if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
+ if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
/* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
- else if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
+ if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
COMPLETE_WITH_CONST("TO");
/* Complete "AS ON <sth> TO" with a table name */
- else if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
+ if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
- else if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
+ if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
"CYCLE", "OWNED BY", "START WITH");
- else if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
+ if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
/* CREATE SERVER <name> */
- else if (Matches3("CREATE", "SERVER", MatchAny))
+ if (Matches3("CREATE", "SERVER", MatchAny))
COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
/* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
/* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
- else if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
+ if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
/* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
- else if (TailMatches2("CREATE", "UNLOGGED"))
+ if (TailMatches2("CREATE", "UNLOGGED"))
COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
/* CREATE TABLESPACE */
- else if (Matches3("CREATE", "TABLESPACE", MatchAny))
+ if (Matches3("CREATE", "TABLESPACE", MatchAny))
COMPLETE_WITH_LIST2("OWNER", "LOCATION");
/* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */
- else if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
+ if (Matches5("CREATE", "TABLESPACE", MatchAny, "OWNER", MatchAny))
COMPLETE_WITH_CONST("LOCATION");
/* CREATE TEXT SEARCH */
- else if (Matches3("CREATE", "TEXT", "SEARCH"))
+ if (Matches3("CREATE", "TEXT", "SEARCH"))
COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
- else if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
+ if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
COMPLETE_WITH_CONST("(");
/* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
/* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
- else if (TailMatches3("CREATE", "TRIGGER", MatchAny))
+ if (TailMatches3("CREATE", "TRIGGER", MatchAny))
COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
/* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
- else if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
+ if (TailMatches4("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER"))
COMPLETE_WITH_LIST4("INSERT", "DELETE", "UPDATE", "TRUNCATE");
/* complete CREATE TRIGGER <name> INSTEAD OF with an event */
- else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
+ if (TailMatches5("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF"))
COMPLETE_WITH_LIST3("INSERT", "DELETE", "UPDATE");
/* complete CREATE TRIGGER <name> BEFORE,AFTER sth with OR,ON */
- else if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
+ if (TailMatches5("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny) ||
TailMatches6("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny))
COMPLETE_WITH_LIST2("ON", "OR");
@@ -2204,17 +1919,17 @@ psql_completion(const char *text, int start, int end)
* complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
* tables
*/
- else if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
+ if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "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 (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
+ if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
/* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
- else if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
+ if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
COMPLETE_WITH_CONST("PROCEDURE");
/* CREATE ROLE,USER,GROUP <name> */
- else if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
+ if (Matches3("CREATE", "ROLE|GROUP|USER", MatchAny) &&
!TailMatches2("USER", "MAPPING"))
{
static const char *const list_CREATEROLE[] =
@@ -2229,7 +1944,7 @@ psql_completion(const char *text, int start, int end)
}
/* CREATE ROLE,USER,GROUP <name> WITH */
- else if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
+ if (Matches4("CREATE", "ROLE|GROUP|USER", MatchAny, "WITH"))
{
/* Similar to the above, but don't complete "WITH" again. */
static const char *const list_CREATEROLE_WITH[] =
@@ -2247,70 +1962,70 @@ psql_completion(const char *text, int start, int end)
* complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
* PASSWORD
*/
- else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
+ if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
COMPLETE_WITH_CONST("PASSWORD");
/* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
- else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
+ if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
COMPLETE_WITH_LIST2("GROUP", "ROLE");
/* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
/* Complete CREATE VIEW <name> with AS */
- else if (TailMatches3("CREATE", "VIEW", MatchAny))
+ if (TailMatches3("CREATE", "VIEW", MatchAny))
COMPLETE_WITH_CONST("AS");
/* Complete "CREATE VIEW <sth> AS with "SELECT" */
- else if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
+ if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
COMPLETE_WITH_CONST("SELECT");
/* CREATE MATERIALIZED VIEW */
- else if (Matches2("CREATE", "MATERIALIZED"))
+ if (Matches2("CREATE", "MATERIALIZED"))
COMPLETE_WITH_CONST("VIEW");
/* Complete CREATE MATERIALIZED VIEW <name> with AS */
- else if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
+ if (Matches4("CREATE", "MATERIALIZED", "VIEW", MatchAny))
COMPLETE_WITH_CONST("AS");
/* Complete "CREATE MATERIALIZED VIEW <sth> AS with "SELECT" */
- else if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
+ if (Matches5("CREATE", "MATERIALIZED", "VIEW", MatchAny, "AS"))
COMPLETE_WITH_CONST("SELECT");
/* CREATE EVENT TRIGGER */
- else if (Matches2("CREATE", "EVENT"))
+ if (Matches2("CREATE", "EVENT"))
COMPLETE_WITH_CONST("TRIGGER");
/* Complete CREATE EVENT TRIGGER <name> with ON */
- else if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
+ if (Matches4("CREATE", "EVENT", "TRIGGER", MatchAny))
COMPLETE_WITH_CONST("ON");
/* Complete CREATE EVENT TRIGGER <name> ON with event_type */
- else if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
+ if (Matches5("CREATE", "EVENT", "TRIGGER", MatchAny, "ON"))
COMPLETE_WITH_LIST3("ddl_command_start", "ddl_command_end", "sql_drop");
/* DECLARE */
- else if (Matches2("DECLARE", MatchAny))
+ if (Matches2("DECLARE", MatchAny))
COMPLETE_WITH_LIST5("BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL",
"CURSOR");
- else if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
+ if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
/* DELETE --- can be inside EXPLAIN, RULE, etc */
/* ... despite which, only complete DELETE with FROM at start of line */
- else if (Matches1("DELETE"))
+ if (Matches1("DELETE"))
COMPLETE_WITH_CONST("FROM");
/* Complete DELETE FROM with a list of tables */
- else if (TailMatches2("DELETE", "FROM"))
+ if (TailMatches2("DELETE", "FROM"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
/* Complete DELETE FROM <table> */
- else if (TailMatches3("DELETE", "FROM", MatchAny))
+ if (TailMatches3("DELETE", "FROM", MatchAny))
COMPLETE_WITH_LIST2("USING", "WHERE");
/* XXX: implement tab completion for DELETE ... USING */
/* DISCARD */
- else if (Matches1("DISCARD"))
+ if (Matches1("DISCARD"))
COMPLETE_WITH_LIST4("ALL", "PLANS", "SEQUENCES", "TEMP");
/* DO */
- else if (Matches1("DO"))
+ if (Matches1("DO"))
COMPLETE_WITH_CONST("LANGUAGE");
/* DROP */
/* Complete DROP object with CASCADE / RESTRICT */
- else if (Matches3("DROP",
+ if (Matches3("DROP",
"COLLATION|CONVERSION|DOMAIN|EXTENSION|LANGUAGE|SCHEMA|SEQUENCE|SERVER|TABLE|TYPE|VIEW",
MatchAny) ||
Matches4("DROP", "ACCESS", "METHOD", MatchAny) ||
@@ -2323,88 +2038,88 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
/* help completing some of the variants */
- else if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
+ if (Matches3("DROP", "AGGREGATE|FUNCTION", MatchAny))
COMPLETE_WITH_CONST("(");
- else if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
+ if (Matches4("DROP", "AGGREGATE|FUNCTION", MatchAny, "("))
COMPLETE_WITH_FUNCTION_ARG(prev2_wd);
- else if (Matches2("DROP", "FOREIGN"))
+ if (Matches2("DROP", "FOREIGN"))
COMPLETE_WITH_LIST2("DATA WRAPPER", "TABLE");
/* DROP INDEX */
- else if (Matches2("DROP", "INDEX"))
+ if (Matches2("DROP", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
" UNION SELECT 'CONCURRENTLY'");
- else if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
+ if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
- else if (Matches3("DROP", "INDEX", MatchAny))
+ if (Matches3("DROP", "INDEX", MatchAny))
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
- else if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
+ if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
/* DROP MATERIALIZED VIEW */
- else if (Matches2("DROP", "MATERIALIZED"))
+ if (Matches2("DROP", "MATERIALIZED"))
COMPLETE_WITH_CONST("VIEW");
- else if (Matches3("DROP", "MATERIALIZED", "VIEW"))
+ if (Matches3("DROP", "MATERIALIZED", "VIEW"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
/* DROP OWNED BY */
- else if (Matches2("DROP", "OWNED"))
+ if (Matches2("DROP", "OWNED"))
COMPLETE_WITH_CONST("BY");
- else if (Matches3("DROP", "OWNED", "BY"))
+ if (Matches3("DROP", "OWNED", "BY"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
- else if (Matches3("DROP", "TEXT", "SEARCH"))
+ if (Matches3("DROP", "TEXT", "SEARCH"))
COMPLETE_WITH_LIST4("CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE");
/* DROP TRIGGER */
- else if (Matches3("DROP", "TRIGGER", MatchAny))
+ if (Matches3("DROP", "TRIGGER", MatchAny))
COMPLETE_WITH_CONST("ON");
- else if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
+ if (Matches4("DROP", "TRIGGER", MatchAny, "ON"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
}
- else if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
+ if (Matches5("DROP", "TRIGGER", MatchAny, "ON", MatchAny))
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
/* DROP ACCESS METHOD */
- else if (Matches2("DROP", "ACCESS"))
+ if (Matches2("DROP", "ACCESS"))
COMPLETE_WITH_CONST("METHOD");
- else if (Matches3("DROP", "ACCESS", "METHOD"))
+ if (Matches3("DROP", "ACCESS", "METHOD"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
/* DROP EVENT TRIGGER */
- else if (Matches2("DROP", "EVENT"))
+ if (Matches2("DROP", "EVENT"))
COMPLETE_WITH_CONST("TRIGGER");
- else if (Matches3("DROP", "EVENT", "TRIGGER"))
+ if (Matches3("DROP", "EVENT", "TRIGGER"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
/* DROP POLICY <name> */
- else if (Matches2("DROP", "POLICY"))
+ if (Matches2("DROP", "POLICY"))
COMPLETE_WITH_QUERY(Query_for_list_of_policies);
/* DROP POLICY <name> ON */
- else if (Matches3("DROP", "POLICY", MatchAny))
+ if (Matches3("DROP", "POLICY", MatchAny))
COMPLETE_WITH_CONST("ON");
/* DROP POLICY <name> ON <table> */
- else if (Matches4("DROP", "POLICY", MatchAny, "ON"))
+ if (Matches4("DROP", "POLICY", MatchAny, "ON"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy);
}
/* DROP RULE */
- else if (Matches3("DROP", "RULE", MatchAny))
+ if (Matches3("DROP", "RULE", MatchAny))
COMPLETE_WITH_CONST("ON");
- else if (Matches4("DROP", "RULE", MatchAny, "ON"))
+ if (Matches4("DROP", "RULE", MatchAny, "ON"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
}
- else if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
+ if (Matches5("DROP", "RULE", MatchAny, "ON", MatchAny))
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
/* EXECUTE */
- else if (Matches1("EXECUTE"))
+ if (Matches1("EXECUTE"))
COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements);
/* EXPLAIN */
@@ -2412,22 +2127,22 @@ psql_completion(const char *text, int start, int end)
/*
* Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands
*/
- else if (Matches1("EXPLAIN"))
+ if (Matches1("EXPLAIN"))
COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
"ANALYZE", "VERBOSE");
- else if (Matches2("EXPLAIN", "ANALYZE"))
+ if (Matches2("EXPLAIN", "ANALYZE"))
COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
"VERBOSE");
- else if (Matches2("EXPLAIN", "VERBOSE") ||
+ if (Matches2("EXPLAIN", "VERBOSE") ||
Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
/* FETCH && MOVE */
/* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
- else if (Matches1("FETCH|MOVE"))
+ if (Matches1("FETCH|MOVE"))
COMPLETE_WITH_LIST4("ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE");
/* Complete FETCH <sth> with one of ALL, NEXT, PRIOR */
- else if (Matches2("FETCH|MOVE", MatchAny))
+ if (Matches2("FETCH|MOVE", MatchAny))
COMPLETE_WITH_LIST3("ALL", "NEXT", "PRIOR");
/*
@@ -2435,31 +2150,31 @@ psql_completion(const char *text, int start, int end)
* but we may as well tab-complete both: perhaps some users prefer one
* variant or the other.
*/
- else if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
+ if (Matches3("FETCH|MOVE", MatchAny, MatchAny))
COMPLETE_WITH_LIST2("FROM", "IN");
/* FOREIGN DATA WRAPPER */
/* applies in ALTER/DROP FDW and in CREATE SERVER */
- else if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
+ if (TailMatches3("FOREIGN", "DATA", "WRAPPER") &&
!TailMatches4("CREATE", MatchAny, MatchAny, MatchAny))
COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
/* applies in CREATE SERVER */
- else if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
+ if (TailMatches4("FOREIGN", "DATA", "WRAPPER", MatchAny) &&
HeadMatches2("CREATE", "SERVER"))
COMPLETE_WITH_CONST("OPTIONS");
/* FOREIGN TABLE */
- else if (TailMatches2("FOREIGN", "TABLE") &&
+ if (TailMatches2("FOREIGN", "TABLE") &&
!TailMatches3("CREATE", MatchAny, MatchAny))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
/* FOREIGN SERVER */
- else if (TailMatches2("FOREIGN", "SERVER"))
+ if (TailMatches2("FOREIGN", "SERVER"))
COMPLETE_WITH_QUERY(Query_for_list_of_servers);
/* GRANT && REVOKE --- is allowed inside CREATE SCHEMA, so use TailMatches */
/* Complete GRANT/REVOKE with a list of roles and privileges */
- else if (TailMatches1("GRANT|REVOKE"))
+ if (TailMatches1("GRANT|REVOKE"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles
" UNION SELECT 'SELECT'"
" UNION SELECT 'INSERT'"
@@ -2479,11 +2194,11 @@ psql_completion(const char *text, int start, int end)
* Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
* TO/FROM
*/
- else if (TailMatches2("GRANT|REVOKE", MatchAny))
+ if (TailMatches2("GRANT|REVOKE", MatchAny))
{
if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
COMPLETE_WITH_CONST("ON");
- else if (TailMatches2("GRANT", MatchAny))
+ if (TailMatches2("GRANT", MatchAny))
COMPLETE_WITH_CONST("TO");
else
COMPLETE_WITH_CONST("FROM");
@@ -2500,7 +2215,7 @@ psql_completion(const char *text, int start, int end)
* here will only work if the privilege list contains exactly one
* privilege.
*/
- else if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
+ if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
" UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
" UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
@@ -2518,11 +2233,11 @@ psql_completion(const char *text, int start, int end)
" UNION SELECT 'TABLESPACE'"
" UNION SELECT 'TYPE'");
- else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
+ if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
"TABLES IN SCHEMA");
- else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
+ if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
/*
@@ -2531,27 +2246,27 @@ psql_completion(const char *text, int start, int end)
*
* Complete "GRANT/REVOKE * ON *" with "TO/FROM".
*/
- else if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
+ if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
{
if (TailMatches1("DATABASE"))
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
- else if (TailMatches1("DOMAIN"))
+ if (TailMatches1("DOMAIN"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
- else if (TailMatches1("FUNCTION"))
+ if (TailMatches1("FUNCTION"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
- else if (TailMatches1("LANGUAGE"))
+ if (TailMatches1("LANGUAGE"))
COMPLETE_WITH_QUERY(Query_for_list_of_languages);
- else if (TailMatches1("SCHEMA"))
+ if (TailMatches1("SCHEMA"))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
- else if (TailMatches1("SEQUENCE"))
+ if (TailMatches1("SEQUENCE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
- else if (TailMatches1("TABLE"))
+ if (TailMatches1("TABLE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
- else if (TailMatches1("TABLESPACE"))
+ if (TailMatches1("TABLESPACE"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
- else if (TailMatches1("TYPE"))
+ if (TailMatches1("TYPE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
- else if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
+ if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
COMPLETE_WITH_CONST("TO");
else
COMPLETE_WITH_CONST("FROM");
@@ -2561,18 +2276,18 @@ psql_completion(const char *text, int start, int end)
* Complete "GRANT/REVOKE ... TO/FROM" with username, PUBLIC,
* CURRENT_USER, or SESSION_USER.
*/
- else if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
+ if ((HeadMatches1("GRANT") && TailMatches1("TO")) ||
(HeadMatches1("REVOKE") && TailMatches1("FROM")))
COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles);
/* Complete "GRANT/REVOKE ... ON * *" with TO/FROM */
- else if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
+ if (HeadMatches1("GRANT") && TailMatches3("ON", MatchAny, MatchAny))
COMPLETE_WITH_CONST("TO");
- else if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
+ if (HeadMatches1("REVOKE") && TailMatches3("ON", MatchAny, MatchAny))
COMPLETE_WITH_CONST("FROM");
/* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
- else if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
+ if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
{
if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
COMPLETE_WITH_CONST("TO");
@@ -2581,7 +2296,7 @@ psql_completion(const char *text, int start, int end)
}
/* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
- else if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
+ if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
{
if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
COMPLETE_WITH_CONST("TO");
@@ -2590,7 +2305,7 @@ psql_completion(const char *text, int start, int end)
}
/* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
- else if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
+ if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
{
if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
COMPLETE_WITH_CONST("TO");
@@ -2599,62 +2314,62 @@ psql_completion(const char *text, int start, int end)
}
/* GROUP BY */
- else if (TailMatches3("FROM", MatchAny, "GROUP"))
+ if (TailMatches3("FROM", MatchAny, "GROUP"))
COMPLETE_WITH_CONST("BY");
/* IMPORT FOREIGN SCHEMA */
- else if (Matches1("IMPORT"))
+ if (Matches1("IMPORT"))
COMPLETE_WITH_CONST("FOREIGN SCHEMA");
- else if (Matches2("IMPORT", "FOREIGN"))
+ if (Matches2("IMPORT", "FOREIGN"))
COMPLETE_WITH_CONST("SCHEMA");
/* INSERT --- can be inside EXPLAIN, RULE, etc */
/* Complete INSERT with "INTO" */
- else if (TailMatches1("INSERT"))
+ if (TailMatches1("INSERT"))
COMPLETE_WITH_CONST("INTO");
/* Complete INSERT INTO with table names */
- else if (TailMatches2("INSERT", "INTO"))
+ if (TailMatches2("INSERT", "INTO"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
/* Complete "INSERT INTO <table> (" with attribute names */
- else if (TailMatches4("INSERT", "INTO", MatchAny, "("))
+ if (TailMatches4("INSERT", "INTO", MatchAny, "("))
COMPLETE_WITH_ATTR(prev2_wd, "");
/*
* Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
* "TABLE" or "DEFAULT VALUES"
*/
- else if (TailMatches3("INSERT", "INTO", MatchAny))
+ if (TailMatches3("INSERT", "INTO", MatchAny))
COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
/*
* Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
* "TABLE"
*/
- else if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
+ if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
ends_with(prev_wd, ')'))
COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
/* Insert an open parenthesis after "VALUES" */
- else if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
+ if (TailMatches1("VALUES") && !TailMatches2("DEFAULT", "VALUES"))
COMPLETE_WITH_CONST("(");
/* LOCK */
/* Complete LOCK [TABLE] with a list of tables */
- else if (Matches1("LOCK"))
+ if (Matches1("LOCK"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
" UNION SELECT 'TABLE'");
- else if (Matches2("LOCK", "TABLE"))
+ 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 (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
+ if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
Matches3("LOCK", "TABLE", MatchAny))
COMPLETE_WITH_CONST("IN");
/* Complete LOCK [TABLE] <table> IN with a lock mode */
- else if (Matches3("LOCK", MatchAny, "IN") ||
+ if (Matches3("LOCK", MatchAny, "IN") ||
Matches4("LOCK", "TABLE", MatchAny, "IN"))
COMPLETE_WITH_LIST8("ACCESS SHARE MODE",
"ROW SHARE MODE", "ROW EXCLUSIVE MODE",
@@ -2663,25 +2378,25 @@ psql_completion(const char *text, int start, int end)
"EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE");
/* NOTIFY --- can be inside EXPLAIN, RULE, etc */
- else if (TailMatches1("NOTIFY"))
+ if (TailMatches1("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 (TailMatches1("OPTIONS"))
+ if (TailMatches1("OPTIONS"))
COMPLETE_WITH_CONST("(");
/* OWNER TO - complete with available roles */
- else if (TailMatches2("OWNER", "TO"))
+ if (TailMatches2("OWNER", "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
/* ORDER BY */
- else if (TailMatches3("FROM", MatchAny, "ORDER"))
+ if (TailMatches3("FROM", MatchAny, "ORDER"))
COMPLETE_WITH_CONST("BY");
- else if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
+ if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
COMPLETE_WITH_ATTR(prev3_wd, "");
/* PREPARE xx AS */
- else if (Matches3("PREPARE", MatchAny, "AS"))
+ if (Matches3("PREPARE", MatchAny, "AS"))
COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
/*
@@ -2690,60 +2405,60 @@ psql_completion(const char *text, int start, int end)
*/
/* REASSIGN OWNED BY xxx TO yyy */
- else if (Matches1("REASSIGN"))
+ if (Matches1("REASSIGN"))
COMPLETE_WITH_CONST("OWNED BY");
- else if (Matches2("REASSIGN", "OWNED"))
+ if (Matches2("REASSIGN", "OWNED"))
COMPLETE_WITH_CONST("BY");
- else if (Matches3("REASSIGN", "OWNED", "BY"))
+ if (Matches3("REASSIGN", "OWNED", "BY"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
- else if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
+ if (Matches4("REASSIGN", "OWNED", "BY", MatchAny))
COMPLETE_WITH_CONST("TO");
- else if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
+ if (Matches5("REASSIGN", "OWNED", "BY", MatchAny, "TO"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
/* REFRESH MATERIALIZED VIEW */
- else if (Matches1("REFRESH"))
+ if (Matches1("REFRESH"))
COMPLETE_WITH_CONST("MATERIALIZED VIEW");
- else if (Matches2("REFRESH", "MATERIALIZED"))
+ if (Matches2("REFRESH", "MATERIALIZED"))
COMPLETE_WITH_CONST("VIEW");
- else if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
+ if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
" UNION SELECT 'CONCURRENTLY'");
- else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
+ if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
- else if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
+ if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
COMPLETE_WITH_CONST("WITH");
- else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
+ if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
COMPLETE_WITH_CONST("WITH");
- else if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
+ if (Matches5("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH"))
COMPLETE_WITH_LIST2("NO DATA", "DATA");
- else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
+ if (Matches6("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH"))
COMPLETE_WITH_LIST2("NO DATA", "DATA");
- else if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
+ if (Matches6("REFRESH", "MATERIALIZED", "VIEW", MatchAny, "WITH", "NO"))
COMPLETE_WITH_CONST("DATA");
- else if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
+ if (Matches7("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny, "WITH", "NO"))
COMPLETE_WITH_CONST("DATA");
/* REINDEX */
- else if (Matches1("REINDEX"))
+ if (Matches1("REINDEX"))
COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
- else if (Matches2("REINDEX", "TABLE"))
+ if (Matches2("REINDEX", "TABLE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
- else if (Matches2("REINDEX", "INDEX"))
+ if (Matches2("REINDEX", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
- else if (Matches2("REINDEX", "SCHEMA"))
+ if (Matches2("REINDEX", "SCHEMA"))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
- else if (Matches2("REINDEX", "SYSTEM|DATABASE"))
+ if (Matches2("REINDEX", "SYSTEM|DATABASE"))
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
/* SECURITY LABEL */
- else if (Matches1("SECURITY"))
+ if (Matches1("SECURITY"))
COMPLETE_WITH_CONST("LABEL");
- else if (Matches2("SECURITY", "LABEL"))
+ if (Matches2("SECURITY", "LABEL"))
COMPLETE_WITH_LIST2("ON", "FOR");
- else if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
+ if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
COMPLETE_WITH_CONST("ON");
- else if (Matches3("SECURITY", "LABEL", "ON") ||
+ if (Matches3("SECURITY", "LABEL", "ON") ||
Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
{
static const char *const list_SECURITY_LABEL[] =
@@ -2754,7 +2469,7 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_SECURITY_LABEL);
}
- else if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
+ if (Matches5("SECURITY", "LABEL", "ON", MatchAny, MatchAny))
COMPLETE_WITH_CONST("IS");
/* SELECT */
@@ -2762,69 +2477,69 @@ psql_completion(const char *text, int start, int end)
/* SET, RESET, SHOW */
/* Complete with a variable name */
- else if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
+ if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
- else if (Matches1("SHOW"))
+ if (Matches1("SHOW"))
COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
/* Complete "SET TRANSACTION" */
- else if (Matches2("SET", "TRANSACTION"))
+ if (Matches2("SET", "TRANSACTION"))
COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
- else if (Matches2("BEGIN|START", "TRANSACTION") ||
- Matches2("BEGIN", "WORK") ||
- Matches1("BEGIN") ||
- Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
+ if (Matches2("BEGIN|START", "TRANSACTION") ||
+ Matches2("BEGIN", "WORK") ||
+ Matches1("BEGIN") ||
+ Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
- else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
- Matches2("BEGIN", "NOT") ||
- Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
+ if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
+ Matches2("BEGIN", "NOT") ||
+ Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
COMPLETE_WITH_CONST("DEFERRABLE");
- else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
- Matches2("BEGIN", "ISOLATION") ||
- Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
+ if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
+ Matches2("BEGIN", "ISOLATION") ||
+ Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
COMPLETE_WITH_CONST("LEVEL");
- else if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
- Matches3("BEGIN", "ISOLATION", "LEVEL") ||
- Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
+ if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
+ Matches3("BEGIN", "ISOLATION", "LEVEL") ||
+ Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
- else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
- Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
- Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
+ if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
+ Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
+ Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
- else if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
- Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
- Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
+ if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
+ Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
+ Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
COMPLETE_WITH_CONST("READ");
- else if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
- Matches2("BEGIN", "READ") ||
- Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
+ if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
+ Matches2("BEGIN", "READ") ||
+ Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
COMPLETE_WITH_LIST2("ONLY", "WRITE");
/* SET CONSTRAINTS */
- else if (Matches2("SET", "CONSTRAINTS"))
+ 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 (Matches3("SET", "CONSTRAINTS", MatchAny))
+ if (Matches3("SET", "CONSTRAINTS", MatchAny))
COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
/* Complete SET ROLE */
- else if (Matches2("SET", "ROLE"))
+ if (Matches2("SET", "ROLE"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
/* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */
- else if (Matches2("SET", "SESSION"))
+ if (Matches2("SET", "SESSION"))
COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
/* Complete SET SESSION AUTHORIZATION with username */
- else if (Matches3("SET", "SESSION", "AUTHORIZATION"))
+ if (Matches3("SET", "SESSION", "AUTHORIZATION"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
/* Complete RESET SESSION with AUTHORIZATION */
- else if (Matches2("RESET", "SESSION"))
+ if (Matches2("RESET", "SESSION"))
COMPLETE_WITH_CONST("AUTHORIZATION");
/* Complete SET <var> with "TO" */
- else if (Matches2("SET", MatchAny))
+ if (Matches2("SET", MatchAny))
COMPLETE_WITH_CONST("TO");
/* Complete ALTER DATABASE|FUNCTION|ROLE|USER ... SET <name> */
- else if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
+ if (HeadMatches2("ALTER", "DATABASE|FUNCTION|ROLE|USER") &&
TailMatches2("SET", MatchAny))
COMPLETE_WITH_LIST2("FROM CURRENT", "TO");
/* Suggest possible variable values */
- else if (TailMatches3("SET", MatchAny, "TO|="))
+ if (TailMatches3("SET", MatchAny, "TO|="))
{
/* special cased code for individual GUCs */
if (TailMatches2("DateStyle", "TO|="))
@@ -2837,112 +2552,117 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(my_list);
}
- else if (TailMatches2("search_path", "TO|="))
+ if (TailMatches2("search_path", "TO|="))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas
" AND nspname not like 'pg\\_toast%%' "
" AND nspname not like 'pg\\_temp%%' "
" UNION SELECT 'DEFAULT' ");
else
{
- /* generic, type based, GUC support */
+ /* generic, type based, GUC support, guctype is malloc'ed */
char *guctype = get_guctype(prev2_wd);
if (guctype && strcmp(guctype, "enum") == 0)
{
char querybuf[1024];
+ free(guctype);
snprintf(querybuf, sizeof(querybuf), Query_for_enum, prev2_wd);
COMPLETE_WITH_QUERY(querybuf);
}
- else if (guctype && strcmp(guctype, "bool") == 0)
+
+ if (guctype && strcmp(guctype, "bool") == 0)
+ {
+ free(guctype);
COMPLETE_WITH_LIST9("on", "off", "true", "false", "yes", "no",
"1", "0", "DEFAULT");
- else
- COMPLETE_WITH_CONST("DEFAULT");
+ }
if (guctype)
free(guctype);
+
+ COMPLETE_WITH_CONST("DEFAULT");
}
}
/* START TRANSACTION */
- else if (Matches1("START"))
+ if (Matches1("START"))
COMPLETE_WITH_CONST("TRANSACTION");
/* TABLE, but not TABLE embedded in other commands */
- else if (Matches1("TABLE"))
+ if (Matches1("TABLE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
/* TABLESAMPLE */
- else if (TailMatches1("TABLESAMPLE"))
+ if (TailMatches1("TABLESAMPLE"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods);
- else if (TailMatches2("TABLESAMPLE", MatchAny))
+ if (TailMatches2("TABLESAMPLE", MatchAny))
COMPLETE_WITH_CONST("(");
/* TRUNCATE */
- else if (Matches1("TRUNCATE"))
+ if (Matches1("TRUNCATE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* UNLISTEN */
- else if (Matches1("UNLISTEN"))
+ 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 --- can be inside EXPLAIN, RULE, etc */
/* If prev. word is UPDATE suggest a list of tables */
- else if (TailMatches1("UPDATE"))
+ if (TailMatches1("UPDATE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
/* Complete UPDATE <table> with "SET" */
- else if (TailMatches2("UPDATE", MatchAny))
+ if (TailMatches2("UPDATE", MatchAny))
COMPLETE_WITH_CONST("SET");
/* Complete UPDATE <table> SET with list of attributes */
- else if (TailMatches3("UPDATE", MatchAny, "SET"))
+ if (TailMatches3("UPDATE", MatchAny, "SET"))
COMPLETE_WITH_ATTR(prev2_wd, "");
/* UPDATE <table> SET <attr> = */
- else if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
+ if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
COMPLETE_WITH_CONST("=");
/* USER MAPPING */
- else if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
+ if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
COMPLETE_WITH_CONST("FOR");
- else if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
+ 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 (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
+ if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
- else if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
+ if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
COMPLETE_WITH_CONST("SERVER");
- else if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
+ if (Matches7("CREATE|ALTER", "USER", "MAPPING", "FOR", MatchAny, "SERVER", MatchAny))
COMPLETE_WITH_CONST("OPTIONS");
/*
* VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
* VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
*/
- else if (Matches1("VACUUM"))
+ 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 (Matches2("VACUUM", "FULL|FREEZE"))
+ if (Matches2("VACUUM", "FULL|FREEZE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
" UNION SELECT 'ANALYZE'"
" UNION SELECT 'VERBOSE'");
- else if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
+ if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
" UNION SELECT 'VERBOSE'");
- else if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
+ if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
" UNION SELECT 'ANALYZE'");
- else if (Matches2("VACUUM", "VERBOSE"))
+ if (Matches2("VACUUM", "VERBOSE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
" UNION SELECT 'ANALYZE'");
- else if (Matches2("VACUUM", "ANALYZE"))
+ if (Matches2("VACUUM", "ANALYZE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
" UNION SELECT 'VERBOSE'");
- else if (HeadMatches1("VACUUM"))
+ if (HeadMatches1("VACUUM"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
/* WITH [RECURSIVE] */
@@ -2951,114 +2671,114 @@ 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 (Matches1("WITH"))
+ if (Matches1("WITH"))
COMPLETE_WITH_CONST("RECURSIVE");
/* ANALYZE */
/* Complete with list of tables */
- else if (Matches1("ANALYZE"))
+ if (Matches1("ANALYZE"))
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 (TailMatches2(MatchAny, "WHERE"))
+ if (TailMatches2(MatchAny, "WHERE"))
COMPLETE_WITH_ATTR(prev2_wd, "");
/* ... FROM ... */
/* TODO: also include SRF ? */
- else if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
+ if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
/* ... JOIN ... */
- else if (TailMatches1("JOIN"))
+ if (TailMatches1("JOIN"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
/* Backslash commands */
/* TODO: \dc \dd \dl */
- else if (TailMatchesCS1("\\?"))
+ if (TailMatchesCS1("\\?"))
COMPLETE_WITH_LIST_CS3("commands", "options", "variables");
- else if (TailMatchesCS1("\\connect|\\c"))
+ if (TailMatchesCS1("\\connect|\\c"))
{
if (!recognized_connection_string(text))
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
}
- else if (TailMatchesCS2("\\connect|\\c", MatchAny))
+ if (TailMatchesCS2("\\connect|\\c", MatchAny))
{
if (!recognized_connection_string(prev_wd))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
}
- else if (TailMatchesCS1("\\da*"))
+ if (TailMatchesCS1("\\da*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
- else if (TailMatchesCS1("\\dA*"))
+ if (TailMatchesCS1("\\dA*"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
- else if (TailMatchesCS1("\\db*"))
+ if (TailMatchesCS1("\\db*"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
- else if (TailMatchesCS1("\\dD*"))
+ if (TailMatchesCS1("\\dD*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
- else if (TailMatchesCS1("\\des*"))
+ if (TailMatchesCS1("\\des*"))
COMPLETE_WITH_QUERY(Query_for_list_of_servers);
- else if (TailMatchesCS1("\\deu*"))
+ if (TailMatchesCS1("\\deu*"))
COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
- else if (TailMatchesCS1("\\dew*"))
+ if (TailMatchesCS1("\\dew*"))
COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
- else if (TailMatchesCS1("\\df*"))
+ if (TailMatchesCS1("\\df*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
- else if (TailMatchesCS1("\\dFd*"))
+ if (TailMatchesCS1("\\dFd*"))
COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
- else if (TailMatchesCS1("\\dFp*"))
+ if (TailMatchesCS1("\\dFp*"))
COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers);
- else if (TailMatchesCS1("\\dFt*"))
+ if (TailMatchesCS1("\\dFt*"))
COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates);
/* must be at end of \dF alternatives: */
- else if (TailMatchesCS1("\\dF*"))
+ if (TailMatchesCS1("\\dF*"))
COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
- else if (TailMatchesCS1("\\di*"))
+ if (TailMatchesCS1("\\di*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
- else if (TailMatchesCS1("\\dL*"))
+ if (TailMatchesCS1("\\dL*"))
COMPLETE_WITH_QUERY(Query_for_list_of_languages);
- else if (TailMatchesCS1("\\dn*"))
+ if (TailMatchesCS1("\\dn*"))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
- else if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
+ if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
- else if (TailMatchesCS1("\\ds*"))
+ if (TailMatchesCS1("\\ds*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
- else if (TailMatchesCS1("\\dt*"))
+ if (TailMatchesCS1("\\dt*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
- else if (TailMatchesCS1("\\dT*"))
+ if (TailMatchesCS1("\\dT*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
- else if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
+ if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
- else if (TailMatchesCS1("\\dv*"))
+ if (TailMatchesCS1("\\dv*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
- else if (TailMatchesCS1("\\dx*"))
+ if (TailMatchesCS1("\\dx*"))
COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
- else if (TailMatchesCS1("\\dm*"))
+ if (TailMatchesCS1("\\dm*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
- else if (TailMatchesCS1("\\dE*"))
+ if (TailMatchesCS1("\\dE*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
- else if (TailMatchesCS1("\\dy*"))
+ if (TailMatchesCS1("\\dy*"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
/* must be at end of \d alternatives: */
- else if (TailMatchesCS1("\\d*"))
+ if (TailMatchesCS1("\\d*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
- else if (TailMatchesCS1("\\ef"))
+ if (TailMatchesCS1("\\ef"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
- else if (TailMatchesCS1("\\ev"))
+ if (TailMatchesCS1("\\ev"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
- else if (TailMatchesCS1("\\encoding"))
+ if (TailMatchesCS1("\\encoding"))
COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
- else if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
+ if (TailMatchesCS1("\\h") || TailMatchesCS1("\\help"))
COMPLETE_WITH_LIST(sql_commands);
- else if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
+ if (TailMatchesCS1("\\l*") && !TailMatchesCS1("\\lo*"))
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
- else if (TailMatchesCS1("\\password"))
+ if (TailMatchesCS1("\\password"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
- else if (TailMatchesCS1("\\pset"))
+ if (TailMatchesCS1("\\pset"))
{
static const char *const my_list[] =
{"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
@@ -3069,7 +2789,7 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST_CS(my_list);
}
- else if (TailMatchesCS2("\\pset", MatchAny))
+ if (TailMatchesCS2("\\pset", MatchAny))
{
if (TailMatchesCS1("format"))
{
@@ -3079,53 +2799,53 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST_CS(my_list);
}
- else if (TailMatchesCS1("linestyle"))
+ if (TailMatchesCS1("linestyle"))
COMPLETE_WITH_LIST_CS3("ascii", "old-ascii", "unicode");
- else if (TailMatchesCS1("unicode_border_linestyle|"
+ if (TailMatchesCS1("unicode_border_linestyle|"
"unicode_column_linestyle|"
"unicode_header_linestyle"))
COMPLETE_WITH_LIST_CS2("single", "double");
}
- else if (TailMatchesCS1("\\unset"))
+ if (TailMatchesCS1("\\unset"))
{
- matches = complete_from_variables(text, "", "", true);
+ return complete_from_variables(text, "", "", true);
}
- else if (TailMatchesCS1("\\set"))
+ if (TailMatchesCS1("\\set"))
{
- matches = complete_from_variables(text, "", "", false);
+ return complete_from_variables(text, "", "", false);
}
- else if (TailMatchesCS2("\\set", MatchAny))
+ if (TailMatchesCS2("\\set", MatchAny))
{
if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|"
"SINGLELINE|SINGLESTEP"))
COMPLETE_WITH_LIST_CS2("on", "off");
- else if (TailMatchesCS1("COMP_KEYWORD_CASE"))
+ if (TailMatchesCS1("COMP_KEYWORD_CASE"))
COMPLETE_WITH_LIST_CS4("lower", "upper",
"preserve-lower", "preserve-upper");
- else if (TailMatchesCS1("ECHO"))
+ if (TailMatchesCS1("ECHO"))
COMPLETE_WITH_LIST_CS4("errors", "queries", "all", "none");
- else if (TailMatchesCS1("ECHO_HIDDEN"))
+ if (TailMatchesCS1("ECHO_HIDDEN"))
COMPLETE_WITH_LIST_CS3("noexec", "off", "on");
- else if (TailMatchesCS1("HISTCONTROL"))
+ if (TailMatchesCS1("HISTCONTROL"))
COMPLETE_WITH_LIST_CS4("ignorespace", "ignoredups",
"ignoreboth", "none");
- else if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
+ if (TailMatchesCS1("ON_ERROR_ROLLBACK"))
COMPLETE_WITH_LIST_CS3("on", "off", "interactive");
- else if (TailMatchesCS1("SHOW_CONTEXT"))
+ if (TailMatchesCS1("SHOW_CONTEXT"))
COMPLETE_WITH_LIST_CS3("never", "errors", "always");
- else if (TailMatchesCS1("VERBOSITY"))
+ if (TailMatchesCS1("VERBOSITY"))
COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
}
- else if (TailMatchesCS1("\\sf*"))
+ if (TailMatchesCS1("\\sf*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
- else if (TailMatchesCS1("\\sv*"))
+ if (TailMatchesCS1("\\sv*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
- else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
+ if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
"\\ir|\\include_relative|\\o|\\out|"
"\\s|\\w|\\write|\\lo_import"))
{
completion_charp = "\\";
- matches = completion_matches(text, complete_from_files);
+ return completion_matches(text, complete_from_files);
}
/*
@@ -3143,7 +2863,7 @@ psql_completion(const char *text, int start, int end)
{
if (words_after_create[i].query)
COMPLETE_WITH_QUERY(words_after_create[i].query);
- else if (words_after_create[i].squery)
+ if (words_after_create[i].squery)
COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
NULL);
break;
@@ -3151,25 +2871,8 @@ psql_completion(const char *text, int start, int end)
}
}
- /*
- * If we still don't have anything to match we have to fabricate some sort
- * of default list. If we were to just return NULL, readline automatically
- * attempts filename completion, and that's usually no good.
- */
- if (matches == NULL)
- {
- COMPLETE_WITH_CONST("");
-#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
- rl_completion_append_character = '\0';
-#endif
- }
-
- /* free storage */
- free(previous_words);
- free(words_buffer);
-
- /* Return our Grand List O' Matches */
- return matches;
+ /* We found no match */
+ return NULL;
}
--
2.9.2
0002-Make-keywords-case-follow-to-input.patch (text/x-patch, 35.9K) download
From d9015e8d52fc11305e42a704ee9eb3459a62a882 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Wed, 14 Sep 2016 12:48:16 +0900
Subject: [PATCH 2/6] Make keywords' case follow to input
Currently some keywords suggested along with database objects are
always in upper case. This patch changes the behavior so that the case
of the additional keywords follow the setting of COMP_KEYWORD_CASE.
COMPLETE_WITH_ATTR needs completion_charp to be appendable, so this
patch changes it to a PQExpBuffer and adjust COMPLET_WITH_* macros to
that change.
This leaves keywords contained in Query_for_list_of_grant_roles and
Query_for_enum, but it is another problem.
---
src/bin/psql/tab-complete-macros.h | 62 ++++++--
src/bin/psql/tab-complete.c | 300 ++++++++++++++++++++-----------------
2 files changed, 212 insertions(+), 150 deletions(-)
diff --git a/src/bin/psql/tab-complete-macros.h b/src/bin/psql/tab-complete-macros.h
index 8ee52b8..3e91bbe 100644
--- a/src/bin/psql/tab-complete-macros.h
+++ b/src/bin/psql/tab-complete-macros.h
@@ -231,16 +231,46 @@
* 5) The list of attributes of the given table (possibly schema-qualified).
* 6) The list of arguments to the given function (possibly schema-qualified).
*/
-#define COMPLETE_WITH_QUERY(query) \
+#define APPEND_COMP_CHARP(charp) \
+ appendPQExpBufferStr(completion_charp, charp);
+
+#define SET_COMP_CHARP(charp) \
+ resetPQExpBuffer(completion_charp); \
+ APPEND_COMP_CHARP(charp);
+
+#define COMPLETION_CHARP (completion_charp->data)
+
+#define COMPLETE_WITH_QUERY(query) \
+do { \
+ SET_COMP_CHARP(query); \
+ return completion_matches(text, complete_from_query); \
+} while (0)
+
+/*
+ * COMPLETE_WITH_QUERY with additional keywords. Keywords are complete
+ * case-sensitively
+ */
+#define COMPLETE_WITH_QUERY_KW(query, addon) \
do { \
- completion_charp = query; \
+ SET_COMP_CHARP(query); \
+ APPEND_COMP_CHARP(addon); \
return completion_matches(text, complete_from_query); \
} while (0)
-#define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \
+#define COMPLETE_WITH_SCHEMA_QUERY(query) \
do { \
completion_squery = &(query); \
- completion_charp = addon; \
+ return completion_matches(text, complete_from_schema_query); \
+} while (0)
+
+/*
+ * COMPLETE_WITH_SCHEMA_QUERY with additional keywords. Keywords are complete
+ * case-sensitively
+ */
+#define COMPLETE_WITH_SCHEMA_QUERY_KW(query, addon) \
+do { \
+ completion_squery = &(query); \
+ SET_COMP_CHARP(addon); \
return completion_matches(text, complete_from_schema_query); \
} while (0)
@@ -260,7 +290,7 @@ do { \
#define COMPLETE_WITH_CONST(string) \
do { \
- completion_charp = string; \
+ SET_COMP_CHARP(string); \
completion_case_sensitive = false; \
return completion_matches(text, complete_from_const); \
} while (0)
@@ -278,12 +308,14 @@ do { \
false, false, pset.encoding); \
if (_completion_table == NULL) \
{ \
- completion_charp = Query_for_list_of_attributes addon; \
+ SET_COMP_CHARP(Query_for_list_of_attributes); \
+ APPEND_COMP_CHARP(addon); \
completion_info_charp = relation; \
} \
else \
{ \
- completion_charp = Query_for_list_of_attributes_with_schema addon; \
+ SET_COMP_CHARP(Query_for_list_of_attributes_with_schema); \
+ APPEND_COMP_CHARP(addon); \
completion_info_charp = _completion_table; \
completion_info_charp2 = _completion_schema; \
} \
@@ -303,12 +335,12 @@ do { \
false, false, pset.encoding); \
if (_completion_function == NULL) \
{ \
- completion_charp = Query_for_list_of_arguments; \
+ SET_COMP_CHARP(Query_for_list_of_arguments); \
completion_info_charp = function; \
} \
else \
{ \
- completion_charp = Query_for_list_of_arguments_with_schema; \
+ SET_COMP_CHARP(Query_for_list_of_arguments_with_schema); \
completion_info_charp = _completion_function; \
completion_info_charp2 = _completion_schema; \
} \
@@ -400,6 +432,16 @@ do { \
COMPLETE_WITH_LIST_CS(list); \
} while (0)
-
+#define ADDLIST1(s1) additional_kw_query(text, 1, s1)
+#define ADDLIST2(s1, s2) additional_kw_query(text, 2, s1, s2)
+#define ADDLIST3(s1, s2, s3) additional_kw_query(text, 3, s1, s2, s3)
+#define ADDLIST4(s1, s2, s3, s4) \
+ additional_kw_query(text, 4, s1, s2, s3, s4)
+#define ADDLIST13(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13) \
+ additional_kw_query(text, 12, s1, s2, s3, s4, s5, s6, s7, \
+ s8, s9, s10, s11, s12, s13)
+#define ADDLIST15(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15) \
+ additional_kw_query(text, 12, s1, s2, s3, s4, s5, s6, s7, \
+ s8, s9, s10, s11, s12, s13, s14, s15)
#endif /* TAB_COMPLETE_MACROS_H */
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 679e58f..85bb363 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -126,7 +126,7 @@ static int completion_max_records;
* Communication variables set by COMPLETE_WITH_FOO macros and then used by
* the completion callback functions. Ugly but there is no better way.
*/
-static const char *completion_charp; /* to pass a string */
+static PQExpBuffer completion_charp = NULL; /* to pass a string */
static const char *const * completion_charpp; /* to pass a list of strings */
static const char *completion_info_charp; /* to pass a second string */
static const char *completion_info_charp2; /* to pass a third string */
@@ -776,6 +776,7 @@ static char **complete_from_variables(const char *text,
static char *complete_from_files(const char *text, int state);
static char *pg_strdup_keyword_case(const char *s, const char *ref);
+static char *additional_kw_query( const char *ref, int n, ...);
static char *escape_string(const char *text);
static PGresult *exec_query(const char *query);
@@ -947,7 +948,8 @@ psql_completion(const char *text, int start, int end)
#endif
/* Clear a few things. */
- completion_charp = NULL;
+ if (completion_charp == NULL)
+ completion_charp = createPQExpBuffer();
completion_charpp = NULL;
completion_info_charp = NULL;
completion_info_charp2 = NULL;
@@ -1056,8 +1058,8 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER TABLE */
if (Matches2("ALTER", "TABLE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
- "UNION SELECT 'ALL IN TABLESPACE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
+ ADDLIST1("ALL IN TABLESPACE"));
/* ALTER something */
if (Matches1("ALTER"))
@@ -1173,8 +1175,8 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER INDEX */
if (Matches2("ALTER", "INDEX"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
- "UNION SELECT 'ALL IN TABLESPACE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
+ ADDLIST1("ALL IN TABLESPACE"));
/* ALTER INDEX <name> */
if (Matches3("ALTER", "INDEX", MatchAny))
COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
@@ -1202,8 +1204,8 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER MATERIALIZED VIEW */
if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
- "UNION SELECT 'ALL IN TABLESPACE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews,
+ ADDLIST1("ALL IN TABLESPACE"));
/* ALTER USER,ROLE <name> */
if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
@@ -1358,7 +1360,7 @@ psql_completion_internal(const char *text, char **previous_words,
* If we have ALTER TRIGGER <sth> ON, then add the correct tablename
*/
if (Matches4("ALTER", "TRIGGER", MatchAny, "ON"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* ALTER TRIGGER <name> ON <name> */
if (Matches5("ALTER", "TRIGGER", MatchAny, "ON", MatchAny))
@@ -1404,10 +1406,10 @@ psql_completion_internal(const char *text, char **previous_words,
}
/* ALTER TABLE xxx INHERIT */
if (Matches4("ALTER", "TABLE", MatchAny, "INHERIT"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* ALTER TABLE xxx NO INHERIT */
if (Matches5("ALTER", "TABLE", MatchAny, "NO", "INHERIT"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* ALTER TABLE xxx DISABLE */
if (Matches4("ALTER", "TABLE", MatchAny, "DISABLE"))
COMPLETE_WITH_LIST3("ROW LEVEL SECURITY", "RULE", "TRIGGER");
@@ -1424,11 +1426,11 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER TABLE xxx ALTER */
if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
- COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'");
+ COMPLETE_WITH_ATTR(prev2_wd, ADDLIST2("COLUMN", "CONSTRAINT"));
/* ALTER TABLE xxx RENAME */
if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
- COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'");
+ COMPLETE_WITH_ATTR(prev2_wd, ADDLIST3("COLUMN", "CONSTRAINT", "TO"));
if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
COMPLETE_WITH_ATTR(prev3_wd, "");
@@ -1628,9 +1630,10 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST4("WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED");
/* CLUSTER */
if (Matches1("CLUSTER"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tm,
+ ADDLIST1("VERBOSE"));
if (Matches2("CLUSTER", "VERBOSE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm);
/* If we have CLUSTER <sth>, then add "USING" */
if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
COMPLETE_WITH_CONST("USING");
@@ -1677,7 +1680,7 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint);
}
if (Matches4("COMMENT", "ON", "MATERIALIZED", "VIEW"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
@@ -1692,11 +1695,11 @@ psql_completion_internal(const char *text, char **previous_words,
* backslash command).
*/
if (Matches1("COPY|\\copy"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
- " UNION ALL SELECT '('");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
+ ADDLIST1("("));
/* If we have COPY BINARY, complete with list of tables */
if (Matches2("COPY", "BINARY"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* If we have COPY (, complete it with legal commands */
if (Matches2("COPY|\\copy", "("))
COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
@@ -1708,7 +1711,7 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
{
- completion_charp = "";
+ SET_COMP_CHARP("");
return completion_matches(text, complete_from_files);
}
@@ -1777,21 +1780,20 @@ psql_completion_internal(const char *text, char **previous_words,
* existing indexes
*/
if (TailMatches2("CREATE|UNIQUE", "INDEX"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
- " UNION SELECT 'ON'"
- " UNION SELECT 'CONCURRENTLY'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
+ ADDLIST2("ON", "CONCURRENTLY"));
/* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
TailMatches2("INDEX|CONCURRENTLY", "ON"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm);
/*
* Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
* indexes
*/
if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
- " UNION SELECT 'ON'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
+ ADDLIST1("ON"));
/* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
@@ -1826,7 +1828,7 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_CONST("ON");
/* Complete "CREATE POLICY <name> ON <table>" */
if (Matches4("CREATE", "POLICY", MatchAny, "ON"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* Complete "CREATE POLICY <name> ON <table> FOR|TO|USING|WITH CHECK" */
if (Matches5("CREATE", "POLICY", MatchAny, "ON", MatchAny))
COMPLETE_WITH_LIST4("FOR", "TO", "USING (", "WITH CHECK (");
@@ -1864,7 +1866,7 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_CONST("TO");
/* Complete "AS ON <sth> TO" with a table name */
if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
@@ -1920,10 +1922,10 @@ psql_completion_internal(const char *text, char **previous_words,
* tables
*/
if (TailMatches6("CREATE", "TRIGGER", MatchAny, "BEFORE|AFTER", MatchAny, "ON"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */
if (TailMatches7("CREATE", "TRIGGER", MatchAny, "INSTEAD", "OF", MatchAny, "ON"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
/* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
if (HeadMatches2("CREATE", "TRIGGER") && TailMatches1("EXECUTE"))
COMPLETE_WITH_CONST("PROCEDURE");
@@ -2009,7 +2011,7 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_CONST("FROM");
/* Complete DELETE FROM with a list of tables */
if (TailMatches2("DELETE", "FROM"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
/* Complete DELETE FROM <table> */
if (TailMatches3("DELETE", "FROM", MatchAny))
COMPLETE_WITH_LIST2("USING", "WHERE");
@@ -2047,10 +2049,10 @@ psql_completion_internal(const char *text, char **previous_words,
/* DROP INDEX */
if (Matches2("DROP", "INDEX"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes,
- " UNION SELECT 'CONCURRENTLY'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
+ ADDLIST1("CONCURRENTLY"));
if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
if (Matches3("DROP", "INDEX", MatchAny))
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
@@ -2060,7 +2062,7 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches2("DROP", "MATERIALIZED"))
COMPLETE_WITH_CONST("VIEW");
if (Matches3("DROP", "MATERIALIZED", "VIEW"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
/* DROP OWNED BY */
if (Matches2("DROP", "OWNED"))
@@ -2166,7 +2168,7 @@ psql_completion_internal(const char *text, char **previous_words,
/* FOREIGN TABLE */
if (TailMatches2("FOREIGN", "TABLE") &&
!TailMatches3("CREATE", MatchAny, MatchAny))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
/* FOREIGN SERVER */
if (TailMatches2("FOREIGN", "SERVER"))
@@ -2175,20 +2177,10 @@ psql_completion_internal(const char *text, char **previous_words,
/* GRANT && REVOKE --- is allowed inside CREATE SCHEMA, so use TailMatches */
/* Complete GRANT/REVOKE with a list of roles and privileges */
if (TailMatches1("GRANT|REVOKE"))
- COMPLETE_WITH_QUERY(Query_for_list_of_roles
- " UNION SELECT 'SELECT'"
- " UNION SELECT 'INSERT'"
- " UNION SELECT 'UPDATE'"
- " UNION SELECT 'DELETE'"
- " UNION SELECT 'TRUNCATE'"
- " UNION SELECT 'REFERENCES'"
- " UNION SELECT 'TRIGGER'"
- " UNION SELECT 'CREATE'"
- " UNION SELECT 'CONNECT'"
- " UNION SELECT 'TEMPORARY'"
- " UNION SELECT 'EXECUTE'"
- " UNION SELECT 'USAGE'"
- " UNION SELECT 'ALL'");
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
+ ADDLIST13("SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE",
+ "REFERENCES", "TRIGGER", "CREATE", "CONNECT", "TEMPORARY",
+ "EXECUTE", "USAGE", "ALL"));
/*
* Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
@@ -2216,22 +2208,22 @@ psql_completion_internal(const char *text, char **previous_words,
* privilege.
*/
if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
- " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
- " UNION SELECT 'ALL SEQUENCES IN SCHEMA'"
- " UNION SELECT 'ALL TABLES IN SCHEMA'"
- " UNION SELECT 'DATABASE'"
- " UNION SELECT 'DOMAIN'"
- " UNION SELECT 'FOREIGN DATA WRAPPER'"
- " UNION SELECT 'FOREIGN SERVER'"
- " UNION SELECT 'FUNCTION'"
- " UNION SELECT 'LANGUAGE'"
- " UNION SELECT 'LARGE OBJECT'"
- " UNION SELECT 'SCHEMA'"
- " UNION SELECT 'SEQUENCE'"
- " UNION SELECT 'TABLE'"
- " UNION SELECT 'TABLESPACE'"
- " UNION SELECT 'TYPE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tsvmf,
+ ADDLIST15("ALL FUNCTIONS IN SCHEMA",
+ "ALL SEQUENCES IN SCHEMA",
+ "ALL TABLES IN SCHEMA",
+ "DATABASE",
+ "DOMAIN",
+ "FOREIGN DATA WRAPPER",
+ "FOREIGN SERVER",
+ "FUNCTION",
+ "LANGUAGE",
+ "LARGE OBJECT",
+ "SCHEMA",
+ "SEQUENCE",
+ "TABLE",
+ "TABLESPACE",
+ "TYPE"));
if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
@@ -2251,21 +2243,21 @@ psql_completion_internal(const char *text, char **previous_words,
if (TailMatches1("DATABASE"))
COMPLETE_WITH_QUERY(Query_for_list_of_databases);
if (TailMatches1("DOMAIN"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
if (TailMatches1("FUNCTION"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions);
if (TailMatches1("LANGUAGE"))
COMPLETE_WITH_QUERY(Query_for_list_of_languages);
if (TailMatches1("SCHEMA"))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
if (TailMatches1("SEQUENCE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
if (TailMatches1("TABLE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf);
if (TailMatches1("TABLESPACE"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
if (TailMatches1("TYPE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
COMPLETE_WITH_CONST("TO");
else
@@ -2329,7 +2321,7 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_CONST("INTO");
/* Complete INSERT INTO with table names */
if (TailMatches2("INSERT", "INTO"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
/* Complete "INSERT INTO <table> (" with attribute names */
if (TailMatches4("INSERT", "INTO", MatchAny, "("))
COMPLETE_WITH_ATTR(prev2_wd, "");
@@ -2356,10 +2348,10 @@ psql_completion_internal(const char *text, char **previous_words,
/* LOCK */
/* Complete LOCK [TABLE] with a list of tables */
if (Matches1("LOCK"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables,
- " UNION SELECT 'TABLE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
+ ADDLIST1("TABLE"));
if (Matches2("LOCK", "TABLE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* For the following, handle the case of a single table only for now */
@@ -2422,10 +2414,10 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches2("REFRESH", "MATERIALIZED"))
COMPLETE_WITH_CONST("VIEW");
if (Matches3("REFRESH", "MATERIALIZED", "VIEW"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews,
- " UNION SELECT 'CONCURRENTLY'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews,
+ ADDLIST1("CONCURRENTLY"));
if (Matches4("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
if (Matches4("REFRESH", "MATERIALIZED", "VIEW", MatchAny))
COMPLETE_WITH_CONST("WITH");
if (Matches5("REFRESH", "MATERIALIZED", "VIEW", "CONCURRENTLY", MatchAny))
@@ -2443,9 +2435,9 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches1("REINDEX"))
COMPLETE_WITH_LIST5("TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE");
if (Matches2("REINDEX", "TABLE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm);
if (Matches2("REINDEX", "INDEX"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
if (Matches2("REINDEX", "SCHEMA"))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
if (Matches2("REINDEX", "SYSTEM|DATABASE"))
@@ -2515,7 +2507,8 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST2("ONLY", "WRITE");
/* SET CONSTRAINTS */
if (Matches2("SET", "CONSTRAINTS"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_constraints_with_schema,
+ ADDLIST1("ALL"));
/* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
if (Matches3("SET", "CONSTRAINTS", MatchAny))
COMPLETE_WITH_LIST2("DEFERRED", "IMMEDIATE");
@@ -2527,7 +2520,8 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST2("AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION");
/* Complete SET SESSION AUTHORIZATION with username */
if (Matches3("SET", "SESSION", "AUTHORIZATION"))
- COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'");
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
+ ADDLIST1("DEFAULT"));
/* Complete RESET SESSION with AUTHORIZATION */
if (Matches2("RESET", "SESSION"))
COMPLETE_WITH_CONST("AUTHORIZATION");
@@ -2553,10 +2547,10 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST(my_list);
}
if (TailMatches2("search_path", "TO|="))
- COMPLETE_WITH_QUERY(Query_for_list_of_schemas
- " AND nspname not like 'pg\\_toast%%' "
- " AND nspname not like 'pg\\_temp%%' "
- " UNION SELECT 'DEFAULT' ");
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_schemas
+ " AND nspname not like 'pg\\_toast%%' "
+ " AND nspname not like 'pg\\_temp%%' ",
+ ADDLIST1("DEFAULT"));
else
{
/* generic, type based, GUC support, guctype is malloc'ed */
@@ -2591,7 +2585,7 @@ psql_completion_internal(const char *text, char **previous_words,
/* TABLE, but not TABLE embedded in other commands */
if (Matches1("TABLE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations);
/* TABLESAMPLE */
if (TailMatches1("TABLESAMPLE"))
@@ -2601,7 +2595,7 @@ psql_completion_internal(const char *text, char **previous_words,
/* TRUNCATE */
if (Matches1("TRUNCATE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* UNLISTEN */
if (Matches1("UNLISTEN"))
@@ -2610,7 +2604,7 @@ psql_completion_internal(const char *text, char **previous_words,
/* UPDATE --- can be inside EXPLAIN, RULE, etc */
/* If prev. word is UPDATE suggest a list of tables */
if (TailMatches1("UPDATE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
/* Complete UPDATE <table> with "SET" */
if (TailMatches2("UPDATE", MatchAny))
COMPLETE_WITH_CONST("SET");
@@ -2625,10 +2619,8 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
COMPLETE_WITH_CONST("FOR");
if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
- COMPLETE_WITH_QUERY(Query_for_list_of_roles
- " UNION SELECT 'CURRENT_USER'"
- " UNION SELECT 'PUBLIC'"
- " UNION SELECT 'USER'");
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
+ ADDLIST3("CURRENT_USER", "PUBLIC", "USER"));
if (Matches4("ALTER|DROP", "USER", "MAPPING", "FOR"))
COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
if (Matches5("CREATE|ALTER|DROP", "USER", "MAPPING", "FOR", MatchAny))
@@ -2641,29 +2633,26 @@ psql_completion_internal(const char *text, char **previous_words,
* VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
*/
if (Matches1("VACUUM"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
- " UNION SELECT 'FULL'"
- " UNION SELECT 'FREEZE'"
- " UNION SELECT 'ANALYZE'"
- " UNION SELECT 'VERBOSE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tm,
+ ADDLIST4("FULL", "FREEZE",
+ "ANALYZE", "VERBOSE"));
if (Matches2("VACUUM", "FULL|FREEZE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
- " UNION SELECT 'ANALYZE'"
- " UNION SELECT 'VERBOSE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tm,
+ ADDLIST2("ANALYZE", "VERBOSE"));
if (Matches3("VACUUM", "FULL|FREEZE", "ANALYZE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
- " UNION SELECT 'VERBOSE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tm,
+ ADDLIST1("VERBOSE"));
if (Matches3("VACUUM", "FULL|FREEZE", "VERBOSE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
- " UNION SELECT 'ANALYZE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tm,
+ ADDLIST1("ANALYZE"));
if (Matches2("VACUUM", "VERBOSE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
- " UNION SELECT 'ANALYZE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tm,
+ ADDLIST1("ANALYZE"));
if (Matches2("VACUUM", "ANALYZE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm,
- " UNION SELECT 'VERBOSE'");
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tm,
+ ADDLIST1("VERBOSE"));
if (HeadMatches1("VACUUM"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm);
/* WITH [RECURSIVE] */
@@ -2677,7 +2666,7 @@ psql_completion_internal(const char *text, char **previous_words,
/* ANALYZE */
/* Complete with list of tables */
if (Matches1("ANALYZE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf);
/* WHERE */
/* Simple case of the word before the where being the table name */
@@ -2687,11 +2676,11 @@ psql_completion_internal(const char *text, char **previous_words,
/* ... FROM ... */
/* TODO: also include SRF ? */
if (TailMatches1("FROM") && !Matches3("COPY|\\copy", MatchAny, "FROM"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf);
/* ... JOIN ... */
if (TailMatches1("JOIN"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf);
/* Backslash commands */
/* TODO: \dc \dd \dl */
@@ -2708,13 +2697,13 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
}
if (TailMatchesCS1("\\da*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates);
if (TailMatchesCS1("\\dA*"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
if (TailMatchesCS1("\\db*"))
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
if (TailMatchesCS1("\\dD*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
if (TailMatchesCS1("\\des*"))
COMPLETE_WITH_QUERY(Query_for_list_of_servers);
if (TailMatchesCS1("\\deu*"))
@@ -2722,7 +2711,7 @@ psql_completion_internal(const char *text, char **previous_words,
if (TailMatchesCS1("\\dew*"))
COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
if (TailMatchesCS1("\\df*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions);
if (TailMatchesCS1("\\dFd*"))
COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries);
@@ -2735,40 +2724,40 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations);
if (TailMatchesCS1("\\di*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
if (TailMatchesCS1("\\dL*"))
COMPLETE_WITH_QUERY(Query_for_list_of_languages);
if (TailMatchesCS1("\\dn*"))
COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
if (TailMatchesCS1("\\dp") || TailMatchesCS1("\\z"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf);
if (TailMatchesCS1("\\ds*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
if (TailMatchesCS1("\\dt*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
if (TailMatchesCS1("\\dT*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
if (TailMatchesCS1("\\du*") || TailMatchesCS1("\\dg*"))
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
if (TailMatchesCS1("\\dv*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
if (TailMatchesCS1("\\dx*"))
COMPLETE_WITH_QUERY(Query_for_list_of_extensions);
if (TailMatchesCS1("\\dm*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
if (TailMatchesCS1("\\dE*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables);
if (TailMatchesCS1("\\dy*"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
/* must be at end of \d alternatives: */
if (TailMatchesCS1("\\d*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations);
if (TailMatchesCS1("\\ef"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions);
if (TailMatchesCS1("\\ev"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
if (TailMatchesCS1("\\encoding"))
COMPLETE_WITH_QUERY(Query_for_list_of_encodings);
@@ -2837,14 +2826,14 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST_CS3("default", "verbose", "terse");
}
if (TailMatchesCS1("\\sf*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions);
if (TailMatchesCS1("\\sv*"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|"
"\\ir|\\include_relative|\\o|\\out|"
"\\s|\\w|\\write|\\lo_import"))
{
- completion_charp = "\\";
+ SET_COMP_CHARP("\\");
return completion_matches(text, complete_from_files);
}
@@ -2864,8 +2853,7 @@ psql_completion_internal(const char *text, char **previous_words,
if (words_after_create[i].query)
COMPLETE_WITH_QUERY(words_after_create[i].query);
if (words_after_create[i].squery)
- COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery,
- NULL);
+ COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery);
break;
}
}
@@ -3112,13 +3100,13 @@ _complete_from_query(int is_schema_query, const char *text, int state)
char_length, e_text);
/* If an addon query was provided, use it */
- if (completion_charp)
- appendPQExpBuffer(&query_buffer, "\n%s", completion_charp);
+ if (COMPLETION_CHARP[0])
+ appendPQExpBuffer(&query_buffer, "\n%s", COMPLETION_CHARP);
}
else
{
/* completion_charp is an sprintf-style format string */
- appendPQExpBuffer(&query_buffer, completion_charp,
+ appendPQExpBuffer(&query_buffer, COMPLETION_CHARP,
char_length, e_text,
e_info_charp, e_info_charp,
e_info_charp2, e_info_charp2);
@@ -3233,18 +3221,17 @@ complete_from_list(const char *text, int state)
static char *
complete_from_const(const char *text, int state)
{
- Assert(completion_charp != NULL);
if (state == 0)
{
if (completion_case_sensitive)
- return pg_strdup(completion_charp);
+ return pg_strdup(COMPLETION_CHARP);
else
/*
* If case insensitive matching was requested initially, adjust
* the case according to setting.
*/
- return pg_strdup_keyword_case(completion_charp, text);
+ return pg_strdup_keyword_case(COMPLETION_CHARP, text);
}
else
return NULL;
@@ -3345,7 +3332,7 @@ complete_from_files(const char *text, int state)
if (state == 0)
{
/* Initialization: stash the unquoted input. */
- unquoted_text = strtokx(text, "", NULL, "'", *completion_charp,
+ unquoted_text = strtokx(text, "", NULL, "'", COMPLETION_CHARP[0],
false, true, pset.encoding);
/* expect a NULL return for the empty string only */
if (!unquoted_text)
@@ -3366,7 +3353,7 @@ complete_from_files(const char *text, int state)
* bother providing a macro to simplify this.
*/
ret = quote_if_needed(unquoted_match, " \t\r\n\"`",
- '\'', *completion_charp, pset.encoding);
+ '\'', COMPLETION_CHARP[0], pset.encoding);
if (ret)
free(unquoted_match);
else
@@ -3410,6 +3397,39 @@ pg_strdup_keyword_case(const char *s, const char *ref)
return ret;
}
+/* Construct codelet to append given keywords */
+static char *
+additional_kw_query(const char *ref, int n, ...)
+{
+ va_list ap;
+ static PQExpBuffer qbuf = NULL;
+ int i;
+
+ if (qbuf == NULL)
+ qbuf = createPQExpBuffer();
+ else
+ resetPQExpBuffer(qbuf);
+
+ /* Construct an additional queriy to append keywords */
+ appendPQExpBufferStr(qbuf, " UNION ALL SELECT * FROM (VALUES ");
+
+ va_start(ap, n);
+ for (i = 0 ; i < n ; i++)
+ {
+ char *item = pg_strdup_keyword_case(va_arg(ap, char *), ref);
+ if (i > 0) appendPQExpBufferChar(qbuf, ',');
+ appendPQExpBufferStr(qbuf, "('");
+ appendPQExpBufferStr(qbuf, item);
+ appendPQExpBufferStr(qbuf, "')");
+ pg_free(item);
+ }
+ va_end(ap);
+
+ appendPQExpBufferStr(qbuf, ") as x");
+
+ return qbuf->data;
+}
+
/*
* escape_string - Escape argument for use as string literal.
--
2.9.2
0003-Fix-suggested-keywords-to-follow-input-in-tab-comple.patch (text/x-patch, 8.9K) download
From 8d68e7102e2200bb99fa913fa936f9bd16b52092 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Fri, 16 Sep 2016 11:36:13 +0900
Subject: [PATCH 3/6] Fix suggested keywords to follow input in tab-completion
session 2
The prevous fix left some completions unfixed. This commit moves
keywords of Query_for_list_of_set_vars/alter_system_set_vars/show_vars
out of the constant and process the keywords as the same as other
syntaxes.
Role name is a bother. PUBLIC, CURRENT_USER, SESSION_USER are
certainly roles and the last two are used in many places. In this
patch I renamed Query_for_list_of_roles to
Query_for_list_of_true_roles and added Query_for_list_of_roles that
having CURRENT_USER and SESSION_USER. But this might be too much.
---
src/bin/psql/tab-complete-macros.h | 2 +
src/bin/psql/tab-complete.c | 100 ++++++++++++++++++++++---------------
2 files changed, 62 insertions(+), 40 deletions(-)
diff --git a/src/bin/psql/tab-complete-macros.h b/src/bin/psql/tab-complete-macros.h
index 3e91bbe..3597004 100644
--- a/src/bin/psql/tab-complete-macros.h
+++ b/src/bin/psql/tab-complete-macros.h
@@ -437,6 +437,8 @@ do { \
#define ADDLIST3(s1, s2, s3) additional_kw_query(text, 3, s1, s2, s3)
#define ADDLIST4(s1, s2, s3, s4) \
additional_kw_query(text, 4, s1, s2, s3, s4)
+#define ADDLIST6(s1, s2, s3, s4, s5, s6) \
+ additional_kw_query(text, 6, s1, s2, s3, s4, s5, s6)
#define ADDLIST13(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13) \
additional_kw_query(text, 12, s1, s2, s3, s4, s5, s6, s7, \
s8, s9, s10, s11, s12, s13)
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 85bb363..3af623c 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -449,43 +449,38 @@ static const SchemaQuery Query_for_list_of_matviews = {
" WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'"
#define Query_for_list_of_alter_system_set_vars \
-"SELECT name FROM "\
-" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
-" WHERE context != 'internal') ss "\
-" WHERE substring(name,1,%d)='%s'"\
-" UNION ALL SELECT 'all' ss"
-
-#define Query_for_list_of_set_vars \
-"SELECT name FROM "\
-" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
-" WHERE context IN ('user', 'superuser') "\
-" UNION ALL SELECT 'constraints' "\
-" UNION ALL SELECT 'transaction' "\
-" UNION ALL SELECT 'session' "\
-" UNION ALL SELECT 'role' "\
-" UNION ALL SELECT 'tablespace' "\
-" UNION ALL SELECT 'all') ss "\
+"SELECT name FROM " \
+" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings " \
+" WHERE context != 'internal') ss " \
" WHERE substring(name,1,%d)='%s'"
+#define Query_for_list_of_set_vars \
+"SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings " \
+" WHERE context IN ('user', 'superuser') " \
+" AND substring(name,1,%d)='%s'"
+
#define Query_for_list_of_show_vars \
-"SELECT name FROM "\
-" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
-" UNION ALL SELECT 'session authorization' "\
-" UNION ALL SELECT 'all') ss "\
+"SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings " \
" WHERE substring(name,1,%d)='%s'"
-#define Query_for_list_of_roles \
+#define Query_for_list_of_true_roles \
" SELECT pg_catalog.quote_ident(rolname) "\
" FROM pg_catalog.pg_roles "\
" WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"
+#define Query_for_list_of_roles \
+ concatenate_strings( \
+ " SELECT pg_catalog.quote_ident(rolname) " \
+ " FROM pg_catalog.pg_roles " \
+ " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'", \
+ ADDLIST2("CURRENT_USER", "SESSION_USER"))
+
#define Query_for_list_of_grant_roles \
-" SELECT pg_catalog.quote_ident(rolname) "\
-" FROM pg_catalog.pg_roles "\
-" WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\
-" UNION ALL SELECT 'PUBLIC'"\
-" UNION ALL SELECT 'CURRENT_USER'"\
-" UNION ALL SELECT 'SESSION_USER'"
+ concatenate_strings( \
+ " SELECT pg_catalog.quote_ident(rolname) " \
+ " FROM pg_catalog.pg_roles " \
+ " WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'", \
+ ADDLIST3("PUBLIC", "CURRENT_USER", "SESSION_USER"))
/* the silly-looking length condition is just to eat up the current word */
#define Query_for_table_owning_index \
@@ -681,13 +676,13 @@ static const SchemaQuery Query_for_list_of_matviews = {
" WHERE pg_catalog.quote_ident(polname)='%s')"
#define Query_for_enum \
-" SELECT name FROM ( "\
-" SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name "\
-" FROM pg_catalog.pg_settings "\
-" WHERE pg_catalog.lower(name)=pg_catalog.lower('%s') "\
-" UNION ALL " \
-" SELECT 'DEFAULT' ) ss "\
-" WHERE pg_catalog.substring(name,1,%%d)='%%s'"
+ concatenate_strings( \
+ " SELECT name FROM ( " \
+ " SELECT pg_catalog.quote_ident(pg_catalog.unnest(enumvals)) AS name " \
+ " FROM pg_catalog.pg_settings " \
+ " WHERE pg_catalog.lower(name)=pg_catalog.lower('%s')) ss " \
+ " WHERE pg_catalog.substring(name,1,%%d)='%%s'", \
+ ADDLIST1("DEFAULT"))
/*
* This is a list of all "things" in Pgsql, which can show up after CREATE or
@@ -727,7 +722,7 @@ static const pgsql_thing_t words_after_create[] = {
{"FOREIGN DATA WRAPPER", NULL, NULL},
{"FOREIGN TABLE", NULL, NULL},
{"FUNCTION", NULL, &Query_for_list_of_functions},
- {"GROUP", Query_for_list_of_roles},
+ {"GROUP", Query_for_list_of_true_roles},
{"LANGUAGE", Query_for_list_of_languages},
{"INDEX", NULL, &Query_for_list_of_indexes},
{"MATERIALIZED VIEW", NULL, &Query_for_list_of_matviews},
@@ -736,7 +731,7 @@ static const pgsql_thing_t words_after_create[] = {
{"OWNED", NULL, NULL, THING_NO_CREATE}, /* for DROP OWNED BY ... */
{"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW},
{"POLICY", NULL, NULL},
- {"ROLE", Query_for_list_of_roles},
+ {"ROLE", Query_for_list_of_true_roles},
{"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
{"SCHEMA", Query_for_list_of_schemas},
{"SEQUENCE", NULL, &Query_for_list_of_sequences},
@@ -751,7 +746,7 @@ static const pgsql_thing_t words_after_create[] = {
{"UNIQUE", NULL, NULL, THING_NO_DROP}, /* for CREATE UNIQUE INDEX ... */
{"UNLOGGED", NULL, NULL, THING_NO_DROP}, /* for CREATE UNLOGGED TABLE
* ... */
- {"USER", Query_for_list_of_roles},
+ {"USER", Query_for_list_of_true_roles},
{"USER MAPPING FOR", NULL, NULL},
{"VIEW", NULL, &Query_for_list_of_views},
{NULL} /* end of list */
@@ -776,6 +771,7 @@ static char **complete_from_variables(const char *text,
static char *complete_from_files(const char *text, int state);
static char *pg_strdup_keyword_case(const char *s, const char *ref);
+static char *concatenate_strings(const char *s1, const char *s2);
static char *additional_kw_query( const char *ref, int n, ...);
static char *escape_string(const char *text);
static PGresult *exec_query(const char *query);
@@ -1296,7 +1292,8 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST2("SET", "RESET");
/* ALTER SYSTEM SET|RESET <name> */
if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
- COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
+ COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars,
+ ADDLIST1("ALL"));
/* ALTER VIEW <name> */
if (Matches3("ALTER", "VIEW", MatchAny))
COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
@@ -2470,9 +2467,12 @@ psql_completion_internal(const char *text, char **previous_words,
/* SET, RESET, SHOW */
/* Complete with a variable name */
if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
- COMPLETE_WITH_QUERY(Query_for_list_of_set_vars);
+ COMPLETE_WITH_QUERY(Query_for_list_of_set_vars,
+ ADDLIST6("CONSTRAINTS", "TRANSACTION", "SESSION",
+ "ROLE", "TABLESPACE", "ALL"));
if (Matches1("SHOW"))
- COMPLETE_WITH_QUERY(Query_for_list_of_show_vars);
+ COMPLETE_WITH_QUERY(Query_for_list_of_show_vars,
+ ADDLIST2("SESSION AUTHORIZATION", "ALL"));
/* Complete "SET TRANSACTION" */
if (Matches2("SET", "TRANSACTION"))
COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
@@ -3397,6 +3397,26 @@ pg_strdup_keyword_case(const char *s, const char *ref)
return ret;
}
+/*
+ * Returns concatenated string.
+ * Note: the internal buffer is static so this cannot be called recursively.
+ */
+static char *
+concatenate_strings(const char *s1, const char *s2)
+{
+ static PQExpBuffer qbuf = NULL;
+
+ if (qbuf == NULL)
+ qbuf = createPQExpBuffer();
+ else
+ resetPQExpBuffer(qbuf);
+
+ appendPQExpBufferStr(qbuf, s1);
+ appendPQExpBufferStr(qbuf, s2);
+
+ return qbuf->data;
+}
+
/* Construct codelet to append given keywords */
static char *
additional_kw_query(const char *ref, int n, ...)
--
2.9.2
0004-Introduce-word-shift-and-removal-feature-to-psql-com.patch (text/x-patch, 49.6K) download
From 1a6d928cfc2eac3aeeeeb19099efccb8f4359abf Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Thu, 15 Sep 2016 14:44:55 +0900
Subject: [PATCH 4/6] Introduce word shift and removal feature to
psql-completion
Currently completion of psql is vulnerable for noise words such like
temp/temporary, unlogged or concurrent. Addition to that, schema
elemsnts in CREATE SCHEMA syntax or some recursive syntaxes are
processed in somewhat bogus way. To accommodate completion mechanism
for the cases, this patch introduces mainly two features.
1. Add a feature to ignore leading words to process. New macros
HEAD_SHIFT, HEAD_SET to shift or set the position of the first word
to match using other macros. All *MatchesN macros follow
this. SHIFT_TO_LAST1 is a macro to shift the head to the position
where the specified word is found last.
2. Add a feature to remove intermediate words from previous_words
list. COLLAPSE(s, n) macro removes n words from the s'th position
(1-based). Removing "noise" words let the succeeding operations
simple.
Using this features, this patch implements the following things.
1. Properly treat schema elements by shifting head.
Now we can treat schema elements as the same as normal syntax by
isolating from leading words. This allow more complex completion for
each create xxxs.
2. Simplify some "||"-connected matches required to cover noise words
by removing noise wors.
CREATE INDEX or some other syntaxes have rather many optional
elements so appropriate to demonstrate how COLLAPSE can be used.
ALTER TABLE/COMMENT/COPY/GRANT/REVOKE/BEGINs.
3. Process recursive of CREATE RULE/EXPLAIN/PREPARE using
Matches/HeadMatches, not with TailMtaches.
The recursive syntaxes are previously completed using TailMatches
instead of Match/HeadMatch but that replacement increases the
restriction in completing the inner commands. psql_complete_internal
can be called recursively and it can be used to resolve this.
The changes in this patch also allows us to encapsulate completion
code for common subsyntaxes in functions but this doesn't that.
---
src/bin/psql/tab-complete-macros.h | 139 +++++++---
src/bin/psql/tab-complete.c | 521 +++++++++++++++++++++----------------
2 files changed, 392 insertions(+), 268 deletions(-)
diff --git a/src/bin/psql/tab-complete-macros.h b/src/bin/psql/tab-complete-macros.h
index 3597004..3a18aa4 100644
--- a/src/bin/psql/tab-complete-macros.h
+++ b/src/bin/psql/tab-complete-macros.h
@@ -25,41 +25,69 @@
#define prev8_wd (previous_words[7])
#define prev9_wd (previous_words[8])
+/* Return the number of stored words counting head shift */
+#define WORD_COUNT() (previous_words_count - head_shift)
+
/*
* Return the index in previous_words for index from the beginning. n is
* 1-based and the result is 0-based.
*/
-#define HEAD_INDEX(n) \
- (previous_words_count - (n))
+#define HEAD_INDEX(n) (WORD_COUNT() - (n))
+
+/* Move the position of the beginning word for matching macros. */
+#define HEAD_SHIFT(n) (head_shift += (n))
+
+/* Set the position of the beginning word for matching macros. */
+#define HEAD_SET(n) (head_shift = (n))
+
+/*
+ * remove n words from current shifted position. This moves entire the
+ * previous_words regardless of head_shift.
+ */
+#define COLLAPSE(s, n) \
+ do { \
+ memmove(previous_words + HEAD_INDEX((s) + (n) - 1), \
+ previous_words + HEAD_INDEX((s) - 1), \
+ sizeof(char *) * \
+ (previous_words_count - HEAD_INDEX((s) - 1))); \
+ previous_words_count -= (n); \
+ } while (0)
+
+/*
+ * Find the position where the specified word appears last and shift to there.
+ * The words before the position will be ignored ever after.
+ */
+#define SHIFT_TO_LAST1(p1) \
+ HEAD_SHIFT(find_last_index_of(p1, previous_words, previous_words_count))
/*
* Macros for matching the last N words before point, and after head_sift,
* case-insensitively.
*/
#define TailMatches1(p1) \
- (previous_words_count >= 1 && \
+ (WORD_COUNT() >= 1 && \
word_matches(p1, prev_wd))
#define TailMatches2(p2, p1) \
- (previous_words_count >= 2 && \
+ (WORD_COUNT() >= 2 && \
word_matches(p1, prev_wd) && \
word_matches(p2, prev2_wd))
#define TailMatches3(p3, p2, p1) \
- (previous_words_count >= 3 && \
+ (WORD_COUNT() >= 3 && \
word_matches(p1, prev_wd) && \
word_matches(p2, prev2_wd) && \
word_matches(p3, prev3_wd))
#define TailMatches4(p4, p3, p2, p1) \
- (previous_words_count >= 4 && \
+ (WORD_COUNT() >= 4 && \
word_matches(p1, prev_wd) && \
word_matches(p2, prev2_wd) && \
word_matches(p3, prev3_wd) && \
word_matches(p4, prev4_wd))
#define TailMatches5(p5, p4, p3, p2, p1) \
- (previous_words_count >= 5 && \
+ (WORD_COUNT() >= 5 && \
word_matches(p1, prev_wd) && \
word_matches(p2, prev2_wd) && \
word_matches(p3, prev3_wd) && \
@@ -67,7 +95,7 @@
word_matches(p5, prev5_wd))
#define TailMatches6(p6, p5, p4, p3, p2, p1) \
- (previous_words_count >= 6 && \
+ (WORD_COUNT() >= 6 && \
word_matches(p1, prev_wd) && \
word_matches(p2, prev2_wd) && \
word_matches(p3, prev3_wd) && \
@@ -76,7 +104,7 @@
word_matches(p6, prev6_wd))
#define TailMatches7(p7, p6, p5, p4, p3, p2, p1) \
- (previous_words_count >= 7 && \
+ (WORD_COUNT() >= 7 && \
word_matches(p1, prev_wd) && \
word_matches(p2, prev2_wd) && \
word_matches(p3, prev3_wd) && \
@@ -86,7 +114,7 @@
word_matches(p7, prev7_wd))
#define TailMatches8(p8, p7, p6, p5, p4, p3, p2, p1) \
- (previous_words_count >= 8 && \
+ (WORD_COUNT() >= 8 && \
word_matches(p1, prev_wd) && \
word_matches(p2, prev2_wd) && \
word_matches(p3, prev3_wd) && \
@@ -97,7 +125,7 @@
word_matches(p8, prev8_wd))
#define TailMatches9(p9, p8, p7, p6, p5, p4, p3, p2, p1) \
- (previous_words_count >= 9 && \
+ (WORD_COUNT() >= 9 && \
word_matches(p1, prev_wd) && \
word_matches(p2, prev2_wd) && \
word_matches(p3, prev3_wd) && \
@@ -113,10 +141,10 @@
* head_shift, case-sensitively.
*/
#define TailMatchesCS1(p1) \
- (previous_words_count >= 1 && \
+ (WORD_COUNT() >= 1 && \
word_matches_cs(p1, prev_wd))
#define TailMatchesCS2(p2, p1) \
- (previous_words_count >= 2 && \
+ (WORD_COUNT() >= 2 && \
word_matches_cs(p1, prev_wd) && \
word_matches_cs(p2, prev2_wd))
@@ -125,31 +153,31 @@
* case-insensitively.
*/
#define Matches1(p1) \
- (previous_words_count == 1 && \
+ (WORD_COUNT() == 1 && \
TailMatches1(p1))
#define Matches2(p1, p2) \
- (previous_words_count == 2 && \
+ (WORD_COUNT() == 2 && \
TailMatches2(p1, p2))
#define Matches3(p1, p2, p3) \
- (previous_words_count == 3 && \
+ (WORD_COUNT() == 3 && \
TailMatches3(p1, p2, p3))
#define Matches4(p1, p2, p3, p4) \
- (previous_words_count == 4 && \
+ (WORD_COUNT() == 4 && \
TailMatches4(p1, p2, p3, p4))
#define Matches5(p1, p2, p3, p4, p5) \
- (previous_words_count == 5 && \
+ (WORD_COUNT() == 5 && \
TailMatches5(p1, p2, p3, p4, p5))
#define Matches6(p1, p2, p3, p4, p5, p6) \
- (previous_words_count == 6 && \
+ (WORD_COUNT() == 6 && \
TailMatches6(p1, p2, p3, p4, p5, p6))
#define Matches7(p1, p2, p3, p4, p5, p6, p7) \
- (previous_words_count == 7 && \
+ (WORD_COUNT() == 7 && \
TailMatches7(p1, p2, p3, p4, p5, p6, p7))
#define Matches8(p1, p2, p3, p4, p5, p6, p7, p8) \
- (previous_words_count == 8 && \
+ (WORD_COUNT() == 8 && \
TailMatches8(p1, p2, p3, p4, p5, p6, p7, p8))
#define Matches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
- (previous_words_count == 9 && \
+ (WORD_COUNT() == 9 && \
TailMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9))
/*
@@ -195,16 +223,39 @@
word_matches(p5, previous_words[HEAD_INDEX((s) + 4)]) && \
word_matches(p6, previous_words[HEAD_INDEX((s) + 5)]))
-#define MidMatches7(s,p1, p2, p3, p4, p5, p6, p7) \
+#define MidMatches7(s,p1, p2, p3, p4, p5, p6, p7) \
(HEAD_INDEX((s) + 6) >= 0 && \
- word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
- word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
- word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]) && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
+ word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]) && \
word_matches(p4, previous_words[HEAD_INDEX((s) + 3)]) && \
word_matches(p5, previous_words[HEAD_INDEX((s) + 4)]) && \
word_matches(p6, previous_words[HEAD_INDEX((s) + 5)]) && \
word_matches(p7, previous_words[HEAD_INDEX((s) + 6)]))
+#define MidMatches8(s,p1, p2, p3, p4, p5, p6, p7, p8) \
+ (HEAD_INDEX((s) + 7) >= 0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
+ word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]) && \
+ word_matches(p4, previous_words[HEAD_INDEX((s) + 3)]) && \
+ word_matches(p5, previous_words[HEAD_INDEX((s) + 4)]) && \
+ word_matches(p6, previous_words[HEAD_INDEX((s) + 5)]) && \
+ word_matches(p7, previous_words[HEAD_INDEX((s) + 6)]) && \
+ word_matches(p8, previous_words[HEAD_INDEX((s) + 7)]))
+
+#define MidMatches9(s,p1, p2, p3, p4, p5, p6, p7, p8, p9) \
+ (HEAD_INDEX((s) + 8) >= 0 && \
+ word_matches(p1, previous_words[HEAD_INDEX(s)]) && \
+ word_matches(p2, previous_words[HEAD_INDEX((s) + 1)]) && \
+ word_matches(p3, previous_words[HEAD_INDEX((s) + 2)]) && \
+ word_matches(p4, previous_words[HEAD_INDEX((s) + 3)]) && \
+ word_matches(p5, previous_words[HEAD_INDEX((s) + 4)]) && \
+ word_matches(p6, previous_words[HEAD_INDEX((s) + 5)]) && \
+ word_matches(p7, previous_words[HEAD_INDEX((s) + 6)]) && \
+ word_matches(p8, previous_words[HEAD_INDEX((s) + 7)]) && \
+ word_matches(p9, previous_words[HEAD_INDEX((s) + 8)]))
+
#define HeadMatches1(p1) \
MidMatches1(1, p1)
#define HeadMatches2(p1, p2) \
@@ -219,6 +270,10 @@
MidMatches6(1, p1, p2, p3, p4, p5, p6)
#define HeadMatches7(p1, p2, p3, p4, p5, p6, p7) \
MidMatches7(1, p1, p2, p3, p4, p5, p6, p7)
+#define HeadMatches8(p1, p2, p3, p4, p5, p6, p7, p8) \
+ MidMatches8(1, p1, p2, p3, p4, p5, p6, p7, p8)
+#define HeadMatches9(p1, p2, p3, p4, p5, p6, p7, p8, p9) \
+ MidMatches9(1, p1, p2, p3, p4, p5, p6, p7, p8, p9)
/*
* A few macros to ease typing. You can use these to complete the given
@@ -240,12 +295,6 @@
#define COMPLETION_CHARP (completion_charp->data)
-#define COMPLETE_WITH_QUERY(query) \
-do { \
- SET_COMP_CHARP(query); \
- return completion_matches(text, complete_from_query); \
-} while (0)
-
/*
* COMPLETE_WITH_QUERY with additional keywords. Keywords are complete
* case-sensitively
@@ -257,11 +306,8 @@ do { \
return completion_matches(text, complete_from_query); \
} while (0)
-#define COMPLETE_WITH_SCHEMA_QUERY(query) \
-do { \
- completion_squery = &(query); \
- return completion_matches(text, complete_from_schema_query); \
-} while (0)
+#define COMPLETE_WITH_QUERY(query) COMPLETE_WITH_QUERY_KW((query), "")
+
/*
* COMPLETE_WITH_SCHEMA_QUERY with additional keywords. Keywords are complete
@@ -274,6 +320,8 @@ do { \
return completion_matches(text, complete_from_schema_query); \
} while (0)
+#define COMPLETE_WITH_SCHEMA_QUERY(query) COMPLETE_WITH_SCHEMA_QUERY_KW((query), "")
+
#define COMPLETE_WITH_LIST_CS(list) \
do { \
completion_charpp = list; \
@@ -295,7 +343,7 @@ do { \
return completion_matches(text, complete_from_const); \
} while (0)
-#define COMPLETE_WITH_ATTR(relation, addon) \
+#define COMPLETE_WITH_ATTR_KW(relation, addon) \
do { \
char *_completion_schema; \
char *_completion_table; \
@@ -322,6 +370,8 @@ do { \
return completion_matches(text, complete_from_query); \
} while (0)
+#define COMPLETE_WITH_ATTR(relation) COMPLETE_WITH_ATTR_KW((relation), "")
+
#define COMPLETE_WITH_FUNCTION_ARG(function) \
do { \
char *_completion_schema; \
@@ -446,4 +496,17 @@ do { \
additional_kw_query(text, 12, s1, s2, s3, s4, s5, s6, s7, \
s8, s9, s10, s11, s12, s13, s14, s15)
+#define COMPLETE_THING(p) \
+do { \
+ const pgsql_thing_t *ent = find_thing_entry(previous_words[-(p) - 1]); \
+ if (ent) \
+ { \
+ if (ent->query) \
+ COMPLETE_WITH_QUERY(ent->query); \
+ else if (ent->squery) \
+ COMPLETE_WITH_SCHEMA_QUERY(*ent->squery); \
+ } \
+ return NULL; \
+} while (0)
+
#endif /* TAB_COMPLETE_MACROS_H */
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 3af623c..7a880d9 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -770,6 +770,7 @@ static char **complete_from_variables(const char *text,
const char *prefix, const char *suffix, bool need_value);
static char *complete_from_files(const char *text, int state);
+static int find_last_index_of(char *w, char **previous_words, int len);
static char *pg_strdup_keyword_case(const char *s, const char *ref);
static char *concatenate_strings(const char *s1, const char *s2);
static char *additional_kw_query( const char *ref, int n, ...);
@@ -782,6 +783,7 @@ static char *get_guctype(const char *varname);
static char **psql_completion_internal(const char *text, char **previous_words,
int previous_words_count);
+static const pgsql_thing_t *find_thing_entry(char *word);
#ifdef NOT_USED
static char *quote_file_name(char *text, int match_type, char *quote_pointer);
static char *dequote_file_name(char *text, char quote_char);
@@ -990,6 +992,9 @@ static char **
psql_completion_internal(const char *text, char **previous_words,
int previous_words_count)
{
+ /* The number of prefixing words to be ignored */
+ int head_shift = 0;
+
/* Known command-starting keywords. */
static const char *const sql_commands[] = {
"ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER",
@@ -1040,10 +1045,24 @@ psql_completion_internal(const char *text, char **previous_words,
if (previous_words_count == 0)
COMPLETE_WITH_LIST(sql_commands);
+ /*
+ * If this is in CREATE SCHEMA, seek to the last CREATE and regard it as
+ * current command to complete.
+ */
+ if (HeadMatches2("CREATE", "SCHEMA"))
+ SHIFT_TO_LAST1("CREATE|GRANT");
+
/* CREATE */
/* complete with something you can create */
if (Matches1("CREATE"))
- return completion_matches(text, create_command_generator);
+ {
+ if (head_shift == 0)
+ return completion_matches(text, create_command_generator);
+ else
+ /* schema_element allows some kinds of object */
+ COMPLETE_WITH_LIST5("TABLE", "VIEW", "INDEX", "SEQUENCE",
+ "TRIGGER");
+ }
/* DROP, but not DROP embedded in other commands */
/* complete with something you can drop */
@@ -1292,8 +1311,8 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST2("SET", "RESET");
/* ALTER SYSTEM SET|RESET <name> */
if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
- COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars,
- ADDLIST1("ALL"));
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_alter_system_set_vars,
+ ADDLIST1("ALL"));
/* ALTER VIEW <name> */
if (Matches3("ALTER", "VIEW", MatchAny))
COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
@@ -1423,13 +1442,13 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER TABLE xxx ALTER */
if (Matches4("ALTER", "TABLE", MatchAny, "ALTER"))
- COMPLETE_WITH_ATTR(prev2_wd, ADDLIST2("COLUMN", "CONSTRAINT"));
+ COMPLETE_WITH_ATTR_KW(prev2_wd, ADDLIST2("COLUMN", "CONSTRAINT"));
/* ALTER TABLE xxx RENAME */
if (Matches4("ALTER", "TABLE", MatchAny, "RENAME"))
- COMPLETE_WITH_ATTR(prev2_wd, ADDLIST3("COLUMN", "CONSTRAINT", "TO"));
+ COMPLETE_WITH_ATTR_KW(prev2_wd, ADDLIST3("COLUMN", "CONSTRAINT", "TO"));
if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|RENAME", "COLUMN"))
- COMPLETE_WITH_ATTR(prev3_wd, "");
+ COMPLETE_WITH_ATTR(prev3_wd);
/* ALTER TABLE xxx RENAME yyy */
if (Matches5("ALTER", "TABLE", MatchAny, "RENAME", MatchAnyExcept("CONSTRAINT|TO")))
@@ -1444,7 +1463,7 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
/* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
- COMPLETE_WITH_ATTR(prev3_wd, "");
+ COMPLETE_WITH_ATTR(prev3_wd);
/*
* If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
@@ -1455,26 +1474,25 @@ psql_completion_internal(const char *text, char **previous_words,
completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
}
+ /* Remove COLUMN just after ALTER */
+ if (HeadMatches5("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN"))
+ COLLAPSE(5, 1);
/* ALTER TABLE ALTER [COLUMN] <foo> */
- if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny) ||
- Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
+ if (Matches5("ALTER", "TABLE", MatchAny, "ALTER", MatchAny))
COMPLETE_WITH_LIST4("TYPE", "SET", "RESET", "DROP");
/* ALTER TABLE ALTER [COLUMN] <foo> SET */
- if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET") ||
- Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
+ if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET"))
COMPLETE_WITH_LIST5("(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE");
/* ALTER TABLE ALTER [COLUMN] <foo> SET ( */
- if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "(") ||
- Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
+ if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "("))
COMPLETE_WITH_LIST2("n_distinct", "n_distinct_inherited");
/* ALTER TABLE ALTER [COLUMN] <foo> SET STORAGE */
- if (Matches8("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "SET", "STORAGE") ||
- Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
+ if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "SET", "STORAGE"))
COMPLETE_WITH_LIST4("PLAIN", "EXTERNAL", "EXTENDED", "MAIN");
/* ALTER TABLE ALTER [COLUMN] <foo> DROP */
- if (Matches7("ALTER", "TABLE", MatchAny, "ALTER", "COLUMN", MatchAny, "DROP") ||
- Matches8("ALTER", "TABLE", MatchAny, "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
+ if (Matches6("ALTER", "TABLE", MatchAny, "ALTER", MatchAny, "DROP"))
COMPLETE_WITH_LIST2("DEFAULT", "NOT NULL");
+
if (Matches4("ALTER", "TABLE", MatchAny, "CLUSTER"))
COMPLETE_WITH_CONST("ON");
if (Matches5("ALTER", "TABLE", MatchAny, "CLUSTER", "ON"))
@@ -1596,7 +1614,7 @@ psql_completion_internal(const char *text, char **previous_words,
* of attributes
*/
if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
- COMPLETE_WITH_ATTR(prev3_wd, "");
+ COMPLETE_WITH_ATTR(prev3_wd);
/* ALTER TYPE ALTER ATTRIBUTE <foo> */
if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
COMPLETE_WITH_CONST("TYPE");
@@ -1629,17 +1647,16 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches1("CLUSTER"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tm,
ADDLIST1("VERBOSE"));
- if (Matches2("CLUSTER", "VERBOSE"))
+ /* Remove VERBOSE for further completion */
+ if (HeadMatches2("CLUSTER", "VERBOSE"))
+ COLLAPSE(2, 1);
+ if (Matches1("CLUSTER"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm);
/* If we have CLUSTER <sth>, then add "USING" */
- if (Matches2("CLUSTER", MatchAnyExcept("VERBOSE|ON")))
- COMPLETE_WITH_CONST("USING");
- /* If we have CLUSTER VERBOSE <sth>, then add "USING" */
- if (Matches3("CLUSTER", "VERBOSE", MatchAny))
+ if (Matches2("CLUSTER", MatchAny))
COMPLETE_WITH_CONST("USING");
/* If we have CLUSTER <sth> USING, then add the index as well */
- if (Matches3("CLUSTER", MatchAny, "USING") ||
- Matches4("CLUSTER", "VERBOSE", MatchAny, "USING"))
+ if (Matches3("CLUSTER", MatchAny, "USING"))
{
completion_info_charp = prev2_wd;
COMPLETE_WITH_QUERY(Query_for_index_of_table);
@@ -1680,9 +1697,8 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
if (Matches4("COMMENT", "ON", "EVENT", "TRIGGER"))
COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
- if (Matches4("COMMENT", "ON", MatchAny, MatchAnyExcept("IS")) ||
- Matches5("COMMENT", "ON", MatchAny, MatchAny, MatchAnyExcept("IS")) ||
- Matches6("COMMENT", "ON", MatchAny, MatchAny, MatchAny, MatchAnyExcept("IS")))
+ if (HeadMatches3("COMMENT", "ON", MatchAny) &&
+ TailMatches1(MatchAnyExcept("IS")))
COMPLETE_WITH_CONST("IS");
/* COPY */
@@ -1693,34 +1709,32 @@ psql_completion_internal(const char *text, char **previous_words,
*/
if (Matches1("COPY|\\copy"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
- ADDLIST1("("));
+ ADDLIST2("(", "BINARY"));
/* If we have COPY BINARY, complete with list of tables */
if (Matches2("COPY", "BINARY"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
+ /* Remove BINARY of COPY for further completion */
+ if (HeadMatches2("COPY", "BINARY"))
/* If we have COPY (, complete it with legal commands */
if (Matches2("COPY|\\copy", "("))
COMPLETE_WITH_LIST7("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
/* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
- if (Matches2("COPY|\\copy", MatchAny) ||
- Matches3("COPY", "BINARY", MatchAny))
+ if (Matches2("COPY|\\copy", MatchAny))
COMPLETE_WITH_LIST2("FROM", "TO");
/* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
- if (Matches3("COPY|\\copy", MatchAny, "FROM|TO") ||
- Matches4("COPY", "BINARY", MatchAny, "FROM|TO"))
+ if (Matches3("COPY|\\copy", MatchAny, "FROM|TO"))
{
SET_COMP_CHARP("");
return completion_matches(text, complete_from_files);
}
/* Handle COPY [BINARY] <sth> FROM|TO filename */
- if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
- Matches5("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
+ if (Matches4("COPY|\\copy", MatchAny, "FROM|TO", MatchAny))
COMPLETE_WITH_LIST6("BINARY", "OIDS", "DELIMITER", "NULL", "CSV",
"ENCODING");
/* Handle COPY [BINARY] <sth> FROM|TO filename CSV */
- if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
- Matches6("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
+ if (Matches5("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV"))
COMPLETE_WITH_LIST5("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
"FORCE NOT NULL");
@@ -1767,57 +1781,47 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches5("CREATE", "FOREIGN", "DATA", "WRAPPER", MatchAny))
COMPLETE_WITH_LIST3("HANDLER", "VALIDATOR", "OPTIONS");
- /* CREATE INDEX --- is allowed inside CREATE SCHEMA, so use TailMatches */
+ /* CREATE INDEX */
/* First off we complete CREATE UNIQUE with "INDEX" */
- if (TailMatches2("CREATE", "UNIQUE"))
+ if (Matches2("CREATE", "UNIQUE"))
COMPLETE_WITH_CONST("INDEX");
- /*
- * If we have CREATE|UNIQUE INDEX, then add "ON", "CONCURRENTLY", and
- * existing indexes
- */
- if (TailMatches2("CREATE|UNIQUE", "INDEX"))
+ /* Remove UNIQUE for further completion */
+ if (HeadMatches3("CREATE", "UNIQUE", "INDEX"))
+ COLLAPSE(2, 1);
+ /* Complete with index names as category suggestion and possible keywords */
+ if (Matches2("CREATE", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
ADDLIST2("ON", "CONCURRENTLY"));
- /* Complete ... INDEX|CONCURRENTLY [<name>] ON with a list of tables */
- if (TailMatches3("INDEX|CONCURRENTLY", MatchAny, "ON") ||
- TailMatches2("INDEX|CONCURRENTLY", "ON"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm);
-
- /*
- * Complete CREATE|UNIQUE INDEX CONCURRENTLY with "ON" and existing
- * indexes
- */
- if (TailMatches3("CREATE|UNIQUE", "INDEX", "CONCURRENTLY"))
+ /* Remove CONCURRENTLY for further completion */
+ if (HeadMatches3("CREATE", "INDEX", "CONCURRENTLY"))
+ COLLAPSE(3, 1);
+ /* Complete with existing index names as word category suggestion */
+ if (Matches2("CREATE", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
ADDLIST1("ON"));
- /* Complete CREATE|UNIQUE INDEX [CONCURRENTLY] <sth> with "ON" */
- if (TailMatches3("CREATE|UNIQUE", "INDEX", MatchAny) ||
- TailMatches4("CREATE|UNIQUE", "INDEX", "CONCURRENTLY", MatchAny))
+ /* Suggest ON just after index name */
+ if (Matches3("CREATE", "INDEX", MatchAnyExcept("ON")))
COMPLETE_WITH_CONST("ON");
-
- /*
- * Complete INDEX <name> ON <table> with a list of table columns (which
- * should really be in parens)
- */
- if (TailMatches4("INDEX", MatchAny, "ON", MatchAny) ||
- TailMatches3("INDEX|CONCURRENTLY", "ON", MatchAny))
+ /* Specified index name does matter ever after */
+ if (HeadMatches4("CREATE", "INDEX", MatchAny, "ON"))
+ COLLAPSE(3, 1);
+ /* Complete with table names only*/
+ if (Matches3("CREATE", "INDEX", "ON"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm);
+ /* MatchAny is table name */
+ if (Matches4("CREATE", "INDEX", "ON", MatchAny))
COMPLETE_WITH_LIST2("(", "USING");
- if (TailMatches5("INDEX", MatchAny, "ON", MatchAny, "(") ||
- TailMatches4("INDEX|CONCURRENTLY", "ON", MatchAny, "("))
- COMPLETE_WITH_ATTR(prev2_wd, "");
- /* same if you put in USING */
- if (TailMatches5("ON", MatchAny, "USING", MatchAny, "("))
- COMPLETE_WITH_ATTR(prev4_wd, "");
/* Complete USING with an index method */
- if (TailMatches6("INDEX", MatchAny, MatchAny, "ON", MatchAny, "USING") ||
- TailMatches5("INDEX", MatchAny, "ON", MatchAny, "USING") ||
- TailMatches4("INDEX", "ON", MatchAny, "USING"))
+ if (Matches5("CREATE", "INDEX", "ON", MatchAny, "USING"))
COMPLETE_WITH_QUERY(Query_for_list_of_access_methods);
- if (TailMatches4("ON", MatchAny, "USING", MatchAny) &&
- !TailMatches6("POLICY", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny) &&
- !TailMatches4("FOR", MatchAny, MatchAny, MatchAny))
+ /* Remove "Using xxx" for further completion*/
+ if (HeadMatches6("CREATE", "INDEX", "ON", MatchAny, "USING", MatchAny))
+ COLLAPSE(5, 2);
+ if (Matches4("CREATE", "INDEX", "ON", MatchAny))
COMPLETE_WITH_CONST("(");
+ if (Matches5("CREATE", "INDEX", "ON", MatchAny, "("))
+ COMPLETE_WITH_ATTR(prev2_wd);
/* CREATE POLICY */
/* Complete "CREATE POLICY <name> ON" */
@@ -1849,43 +1853,72 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_CONST("(");
/* CREATE RULE */
- /* Complete "CREATE RULE <sth>" with "AS ON" */
- if (Matches3("CREATE", "RULE", MatchAny))
- COMPLETE_WITH_CONST("AS ON");
- /* Complete "CREATE RULE <sth> AS" with "ON" */
- if (Matches4("CREATE", "RULE", MatchAny, "AS"))
- COMPLETE_WITH_CONST("ON");
- /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
- if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
- COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
- /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
- if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
- COMPLETE_WITH_CONST("TO");
- /* Complete "AS ON <sth> TO" with a table name */
- if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
+ if (HeadMatches2("CREATE", "RULE"))
+ {
+ /* Complete "CREATE RULE <sth>" with "AS ON" */
+ if (Matches3("CREATE", "RULE", MatchAny))
+ COMPLETE_WITH_CONST("AS ON");
+ /* Complete "CREATE RULE <sth> AS" with "ON" */
+ if (Matches4("CREATE", "RULE", MatchAny, "AS"))
+ COMPLETE_WITH_CONST("ON");
+ /* Complete "CREATE RULE <sth> AS ON" with SELECT|UPDATE|INSERT|DELETE */
+ if (Matches5("CREATE", "RULE", MatchAny, "AS", "ON"))
+ COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE");
+ /* Complete "AS ON SELECT|UPDATE|INSERT|DELETE" with a "TO" */
+ if (TailMatches3("AS", "ON", "SELECT|UPDATE|INSERT|DELETE"))
+ COMPLETE_WITH_CONST("TO");
+ /* Complete "AS ON <sth> TO" with a table name */
+ if (TailMatches4("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
+ /* Complete "ON <sth> TO <name>" with DO INSTEAD*/
+ if (TailMatches4("ON", "SELECT|UPDATE|INSERT|DELETE", "TO", MatchAny))
+ COMPLETE_WITH_CONST("DO INSTEAD");
+ /* Complete DO INSTEAD with actions */
+ if (TailMatches2("DO", "INSTEAD"))
+ COMPLETE_WITH_LIST5("SELECT", "INSERT", "UPDATE", "DELETE", "NOTIFY");
+ /* Complete DO INSTEAD and further */
+ SHIFT_TO_LAST1("SELECT|INSERT|UPDATE|DELETE|NOTIFY");
+ if (HeadMatches1("SELECT|INSERT|UPDATE|DELETE|NOTIFY"))
+ return psql_completion_internal(text, previous_words, WORD_COUNT());
+ COMPLETE_WITH_CONST("");
+ }
+
+ /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
+ if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
+ COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
+ /* Remove TEMPORARY/TEMP for further completion */
+ if (HeadMatches3("CREATE", "TEMP|TEMPORARY", "TABLE|VIEW|SEQUENCE"))
+ COLLAPSE(2, 1);
-/* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
- if (TailMatches3("CREATE", "SEQUENCE", MatchAny) ||
- TailMatches4("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
- COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO", "CACHE",
- "CYCLE", "OWNED BY", "START WITH");
- if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO") ||
- TailMatches5("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny, "NO"))
+ /* CREATE SEQUENCE */
+ if (Matches2("CREATE", "SEQUENCE"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
+ if (Matches3("CREATE", "SEQUENCE", MatchAny))
+ COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
+ "CACHE", "CYCLE", "OWNED BY", "START WITH");
+ if (TailMatches4("CREATE", "SEQUENCE", MatchAny, "NO"))
COMPLETE_WITH_LIST3("MINVALUE", "MAXVALUE", "CYCLE");
/* CREATE SERVER <name> */
if (Matches3("CREATE", "SERVER", MatchAny))
COMPLETE_WITH_LIST3("TYPE", "VERSION", "FOREIGN DATA WRAPPER");
-/* CREATE TABLE --- is allowed inside CREATE SCHEMA, so use TailMatches */
- /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
- if (TailMatches2("CREATE", "TEMP|TEMPORARY"))
- COMPLETE_WITH_LIST3("SEQUENCE", "TABLE", "VIEW");
+/* CREATE SCHEMA <name> */
+ if (Matches2("CREATE", "SCHEMA"))
+ COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
+
+/* CREATE TABLE */
/* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
- if (TailMatches2("CREATE", "UNLOGGED"))
+ if (Matches2("CREATE", "UNLOGGED"))
COMPLETE_WITH_LIST2("TABLE", "MATERIALIZED VIEW");
+ /* Remove UNLOGGED for further completion */
+ if (HeadMatches2("CREATE", "UNLOGGED"))
+ COLLAPSE(2, 1);
+ /* Complete CREATE TABLE with existing table names */
+ if (Matches2("CREATE", "TABLE"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
+
/* CREATE TABLESPACE */
if (Matches3("CREATE", "TABLESPACE", MatchAny))
COMPLETE_WITH_LIST2("OWNER", "LOCATION");
@@ -1899,7 +1932,7 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches5("CREATE", "TEXT", "SEARCH", "CONFIGURATION", MatchAny))
COMPLETE_WITH_CONST("(");
-/* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
+/* CREATE TRIGGER */
/* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
if (TailMatches3("CREATE", "TRIGGER", MatchAny))
COMPLETE_WITH_LIST3("BEFORE", "AFTER", "INSTEAD OF");
@@ -1967,12 +2000,12 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
COMPLETE_WITH_LIST2("GROUP", "ROLE");
-/* CREATE VIEW --- is allowed inside CREATE SCHEMA, so use TailMatches */
+/* CREATE VIEW */
/* Complete CREATE VIEW <name> with AS */
- if (TailMatches3("CREATE", "VIEW", MatchAny))
+ if (Matches3("CREATE", "VIEW", MatchAny))
COMPLETE_WITH_CONST("AS");
/* Complete "CREATE VIEW <sth> AS with "SELECT" */
- if (TailMatches4("CREATE", "VIEW", MatchAny, "AS"))
+ if (Matches4("CREATE", "VIEW", MatchAny, "AS"))
COMPLETE_WITH_CONST("SELECT");
/* CREATE MATERIALIZED VIEW */
@@ -2002,15 +2035,15 @@ psql_completion_internal(const char *text, char **previous_words,
if (HeadMatches1("DECLARE") && TailMatches1("CURSOR"))
COMPLETE_WITH_LIST3("WITH HOLD", "WITHOUT HOLD", "FOR");
-/* DELETE --- can be inside EXPLAIN, RULE, etc */
+/* DELETE */
/* ... despite which, only complete DELETE with FROM at start of line */
if (Matches1("DELETE"))
COMPLETE_WITH_CONST("FROM");
/* Complete DELETE FROM with a list of tables */
- if (TailMatches2("DELETE", "FROM"))
+ if (Matches2("DELETE", "FROM"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
/* Complete DELETE FROM <table> */
- if (TailMatches3("DELETE", "FROM", MatchAny))
+ if (Matches3("DELETE", "FROM", MatchAny))
COMPLETE_WITH_LIST2("USING", "WHERE");
/* XXX: implement tab completion for DELETE ... USING */
@@ -2050,14 +2083,17 @@ psql_completion_internal(const char *text, char **previous_words,
ADDLIST1("CONCURRENTLY"));
if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
+ if (HeadMatches3("DROP", "INDEX", "CONCURRENTLY"))
+ COLLAPSE(3, 1);
if (Matches3("DROP", "INDEX", MatchAny))
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
- if (Matches4("DROP", "INDEX", "CONCURRENTLY", MatchAny))
- COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
/* DROP MATERIALIZED VIEW */
if (Matches2("DROP", "MATERIALIZED"))
COMPLETE_WITH_CONST("VIEW");
+
+ /* DROP VIEW is suggested as a general thing */
+
if (Matches3("DROP", "MATERIALIZED", "VIEW"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
@@ -2129,13 +2165,23 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches1("EXPLAIN"))
COMPLETE_WITH_LIST7("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
"ANALYZE", "VERBOSE");
- if (Matches2("EXPLAIN", "ANALYZE"))
+ if (HeadMatches2("EXPLAIN", "ANALYZE"))
+ COLLAPSE(2, 1);
+ if (Matches1("EXPLAIN"))
COMPLETE_WITH_LIST6("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE",
"VERBOSE");
- if (Matches2("EXPLAIN", "VERBOSE") ||
- Matches3("EXPLAIN", "ANALYZE", "VERBOSE"))
+ if (HeadMatches2("EXPLAIN", "VERBOSE"))
+ COLLAPSE(2, 1);
+ if (Matches1("EXPLAIN"))
COMPLETE_WITH_LIST5("SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE");
+ /* complete on individual syntaxes here after */
+ if (Matches2("EXPLAIN", "SELECT|INSERT|DELETE|UPDATE|DECLARE"))
+ {
+ COLLAPSE(1, 1);
+ return psql_completion_internal(text, previous_words, WORD_COUNT());
+ }
+
/* FETCH && MOVE */
/* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */
if (Matches1("FETCH|MOVE"))
@@ -2171,9 +2217,9 @@ psql_completion_internal(const char *text, char **previous_words,
if (TailMatches2("FOREIGN", "SERVER"))
COMPLETE_WITH_QUERY(Query_for_list_of_servers);
-/* GRANT && REVOKE --- is allowed inside CREATE SCHEMA, so use TailMatches */
+/* GRANT && REVOKE */
/* Complete GRANT/REVOKE with a list of roles and privileges */
- if (TailMatches1("GRANT|REVOKE"))
+ if (Matches1("GRANT|REVOKE"))
COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
ADDLIST13("SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE",
"REFERENCES", "TRIGGER", "CREATE", "CONNECT", "TEMPORARY",
@@ -2183,13 +2229,13 @@ psql_completion_internal(const char *text, char **previous_words,
* Complete GRANT/REVOKE <privilege> with "ON", GRANT/REVOKE <role> with
* TO/FROM
*/
- if (TailMatches2("GRANT|REVOKE", MatchAny))
+ if (Matches2("GRANT|REVOKE", MatchAny))
{
if (TailMatches1("SELECT|INSERT|UPDATE|DELETE|TRUNCATE|REFERENCES|TRIGGER|CREATE|CONNECT|TEMPORARY|TEMP|EXECUTE|USAGE|ALL"))
COMPLETE_WITH_CONST("ON");
- if (TailMatches2("GRANT", MatchAny))
+ if (HeadMatches1("GRANT")) /* GRANT roles */
COMPLETE_WITH_CONST("TO");
- else
+ else /* REVOKE roles */
COMPLETE_WITH_CONST("FROM");
}
@@ -2204,7 +2250,7 @@ psql_completion_internal(const char *text, char **previous_words,
* here will only work if the privilege list contains exactly one
* privilege.
*/
- if (TailMatches3("GRANT|REVOKE", MatchAny, "ON"))
+ if (Matches3("GRANT|REVOKE", MatchAny, "ON"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tsvmf,
ADDLIST15("ALL FUNCTIONS IN SCHEMA",
"ALL SEQUENCES IN SCHEMA",
@@ -2222,11 +2268,11 @@ psql_completion_internal(const char *text, char **previous_words,
"TABLESPACE",
"TYPE"));
- if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
+ if (Matches4("GRANT|REVOKE", MatchAny, "ON", "ALL"))
COMPLETE_WITH_LIST3("FUNCTIONS IN SCHEMA", "SEQUENCES IN SCHEMA",
"TABLES IN SCHEMA");
- if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
+ if (Matches4("GRANT|REVOKE", MatchAny, "ON", "FOREIGN"))
COMPLETE_WITH_LIST2("DATA WRAPPER", "SERVER");
/*
@@ -2235,27 +2281,11 @@ psql_completion_internal(const char *text, char **previous_words,
*
* Complete "GRANT/REVOKE * ON *" with "TO/FROM".
*/
- if (TailMatches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
+ if (Matches4("GRANT|REVOKE", MatchAny, "ON", MatchAny))
{
- if (TailMatches1("DATABASE"))
- COMPLETE_WITH_QUERY(Query_for_list_of_databases);
- if (TailMatches1("DOMAIN"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains);
- if (TailMatches1("FUNCTION"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions);
- if (TailMatches1("LANGUAGE"))
- COMPLETE_WITH_QUERY(Query_for_list_of_languages);
- if (TailMatches1("SCHEMA"))
- COMPLETE_WITH_QUERY(Query_for_list_of_schemas);
- if (TailMatches1("SEQUENCE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
- if (TailMatches1("TABLE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf);
- if (TailMatches1("TABLESPACE"))
- COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
- if (TailMatches1("TYPE"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes);
- if (TailMatches4("GRANT", MatchAny, MatchAny, MatchAny))
+ if (TailMatches1("DATABASE|DOMAIN|FUNCTION|LANGUAGE|SCHEMA|SEQUENCE|TABLE|TABLESPACE|TYPE"))
+ COMPLETE_THING(-1);
+ if (HeadMatches1("GRANT"))
COMPLETE_WITH_CONST("TO");
else
COMPLETE_WITH_CONST("FROM");
@@ -2276,27 +2306,13 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_CONST("FROM");
/* Complete "GRANT/REVOKE * ON ALL * IN SCHEMA *" with TO/FROM */
- if (TailMatches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny))
- {
- if (TailMatches8("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
- COMPLETE_WITH_CONST("TO");
- else
- COMPLETE_WITH_CONST("FROM");
- }
-
/* Complete "GRANT/REVOKE * ON FOREIGN DATA WRAPPER *" with TO/FROM */
- if (TailMatches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny))
- {
- if (TailMatches7("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
- COMPLETE_WITH_CONST("TO");
- else
- COMPLETE_WITH_CONST("FROM");
- }
-
/* Complete "GRANT/REVOKE * ON FOREIGN SERVER *" with TO/FROM */
- if (TailMatches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
+ if (Matches8("GRANT|REVOKE", MatchAny, "ON", "ALL", MatchAny, "IN", "SCHEMA", MatchAny) ||
+ Matches7("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "DATA", "WRAPPER", MatchAny) ||
+ Matches6("GRANT|REVOKE", MatchAny, "ON", "FOREIGN", "SERVER", MatchAny))
{
- if (TailMatches6("GRANT", MatchAny, MatchAny, MatchAny, MatchAny, MatchAny))
+ if (HeadMatches1("GRANT"))
COMPLETE_WITH_CONST("TO");
else
COMPLETE_WITH_CONST("FROM");
@@ -2312,29 +2328,29 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches2("IMPORT", "FOREIGN"))
COMPLETE_WITH_CONST("SCHEMA");
-/* INSERT --- can be inside EXPLAIN, RULE, etc */
+/* INSERT */
/* Complete INSERT with "INTO" */
- if (TailMatches1("INSERT"))
+ if (Matches1("INSERT"))
COMPLETE_WITH_CONST("INTO");
/* Complete INSERT INTO with table names */
- if (TailMatches2("INSERT", "INTO"))
+ if (Matches2("INSERT", "INTO"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
/* Complete "INSERT INTO <table> (" with attribute names */
- if (TailMatches4("INSERT", "INTO", MatchAny, "("))
- COMPLETE_WITH_ATTR(prev2_wd, "");
+ if (Matches4("INSERT", "INTO", MatchAny, "("))
+ COMPLETE_WITH_ATTR(prev2_wd);
/*
* Complete INSERT INTO <table> with "(" or "VALUES" or "SELECT" or
* "TABLE" or "DEFAULT VALUES"
*/
- if (TailMatches3("INSERT", "INTO", MatchAny))
+ if (Matches3("INSERT", "INTO", MatchAny))
COMPLETE_WITH_LIST5("(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES");
/*
* Complete INSERT INTO <table> (attribs) with "VALUES" or "SELECT" or
* "TABLE"
*/
- if (TailMatches4("INSERT", "INTO", MatchAny, MatchAny) &&
+ if (Matches4("INSERT", "INTO", MatchAny, MatchAny) &&
ends_with(prev_wd, ')'))
COMPLETE_WITH_LIST3("SELECT", "TABLE", "VALUES");
@@ -2352,22 +2368,26 @@ psql_completion_internal(const char *text, char **previous_words,
/* For the following, handle the case of a single table only for now */
+ /* Remove TABLE and ONLY from LOCK */
+ if (HeadMatches3("LOCK", "TABLE", MatchAny))
+ COLLAPSE(2, 1);
+ if (HeadMatches3("LOCK", "ONLY", MatchAny))
+ COLLAPSE(2, 1);
+
/* Complete LOCK [TABLE] <table> with "IN" */
- if (Matches2("LOCK", MatchAnyExcept("TABLE")) ||
- Matches3("LOCK", "TABLE", MatchAny))
+ if (Matches2("LOCK", MatchAnyExcept("TABLE")))
COMPLETE_WITH_CONST("IN");
/* Complete LOCK [TABLE] <table> IN with a lock mode */
- if (Matches3("LOCK", MatchAny, "IN") ||
- Matches4("LOCK", "TABLE", MatchAny, "IN"))
+ if (Matches3("LOCK", MatchAny, "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 --- can be inside EXPLAIN, RULE, etc */
- if (TailMatches1("NOTIFY"))
+/* NOTIFY */
+ 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 */
@@ -2382,11 +2402,18 @@ psql_completion_internal(const char *text, char **previous_words,
if (TailMatches3("FROM", MatchAny, "ORDER"))
COMPLETE_WITH_CONST("BY");
if (TailMatches4("FROM", MatchAny, "ORDER", "BY"))
- COMPLETE_WITH_ATTR(prev3_wd, "");
+ COMPLETE_WITH_ATTR(prev3_wd);
/* PREPARE xx AS */
- if (Matches3("PREPARE", MatchAny, "AS"))
- COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
+ if (HeadMatches1("PREPARE"))
+ {
+ if (Matches3("PREPARE", MatchAny, "AS"))
+ COMPLETE_WITH_LIST4("SELECT", "UPDATE", "INSERT", "DELETE FROM");
+
+ /* Complete for indivisual command */
+ SHIFT_TO_LAST1("SELECT|UPDATE|INSERT|DELETE");
+ return psql_completion_internal(text, previous_words, WORD_COUNT());
+ }
/*
* PREPARE TRANSACTION is missing on purpose. It's intended for transaction
@@ -2447,8 +2474,9 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST2("ON", "FOR");
if (Matches4("SECURITY", "LABEL", "FOR", MatchAny))
COMPLETE_WITH_CONST("ON");
- if (Matches3("SECURITY", "LABEL", "ON") ||
- Matches5("SECURITY", "LABEL", "FOR", MatchAny, "ON"))
+ if (HeadMatches4("SECURITY", "LABEL", "FOR", MatchAny))
+ COLLAPSE(3, 2);
+ if (Matches3("SECURITY", "LABEL", "ON"))
{
static const char *const list_SECURITY_LABEL[] =
{"TABLE", "COLUMN", "AGGREGATE", "DATABASE", "DOMAIN",
@@ -2467,44 +2495,51 @@ psql_completion_internal(const char *text, char **previous_words,
/* SET, RESET, SHOW */
/* Complete with a variable name */
if (TailMatches1("SET|RESET") && !TailMatches3("UPDATE", MatchAny, "SET"))
- COMPLETE_WITH_QUERY(Query_for_list_of_set_vars,
- ADDLIST6("CONSTRAINTS", "TRANSACTION", "SESSION",
- "ROLE", "TABLESPACE", "ALL"));
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_set_vars,
+ ADDLIST6("CONSTRAINTS", "TRANSACTION", "SESSION",
+ "ROLE", "TABLESPACE", "ALL"));
if (Matches1("SHOW"))
- COMPLETE_WITH_QUERY(Query_for_list_of_show_vars,
- ADDLIST2("SESSION AUTHORIZATION", "ALL"));
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_show_vars,
+ ADDLIST2("SESSION AUTHORIZATION", "ALL"));
/* Complete "SET TRANSACTION" */
if (Matches2("SET", "TRANSACTION"))
COMPLETE_WITH_LIST5("SNAPSHOT", "ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
- if (Matches2("BEGIN|START", "TRANSACTION") ||
- Matches2("BEGIN", "WORK") ||
- Matches1("BEGIN") ||
- Matches5("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION"))
- COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE", "NOT DEFERRABLE");
- if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "NOT") ||
- Matches2("BEGIN", "NOT") ||
- Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "NOT"))
- COMPLETE_WITH_CONST("DEFERRABLE");
- if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION") ||
- Matches2("BEGIN", "ISOLATION") ||
- Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION"))
- COMPLETE_WITH_CONST("LEVEL");
- if (Matches4("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL") ||
- Matches3("BEGIN", "ISOLATION", "LEVEL") ||
- Matches7("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL"))
- COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
- if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "READ") ||
- Matches4("BEGIN", "ISOLATION", "LEVEL", "READ") ||
- Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "READ"))
- COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
- if (Matches5("SET|BEGIN|START", "TRANSACTION|WORK", "ISOLATION", "LEVEL", "REPEATABLE") ||
- Matches4("BEGIN", "ISOLATION", "LEVEL", "REPEATABLE") ||
- Matches8("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "ISOLATION", "LEVEL", "REPEATABLE"))
- COMPLETE_WITH_CONST("READ");
- if (Matches3("SET|BEGIN|START", "TRANSACTION|WORK", "READ") ||
- Matches2("BEGIN", "READ") ||
- Matches6("SET", "SESSION", "CHARACTERISTICS", "AS", "TRANSACTION", "READ"))
- COMPLETE_WITH_LIST2("ONLY", "WRITE");
+ if (HeadMatches2("BEGIN", "WORK|TRANSACTION"))
+ COLLAPSE(2, 1);
+ {
+ int shift = 0;
+
+ if (HeadMatches2("START", "TRANSACTION"))
+ shift = 2;
+ if (HeadMatches1("BEGIN"))
+ shift = 1;
+ if (HeadMatches5("SET", "SESSION", "CHARACTERISTICS", "AS",
+ "TRANSACTION"))
+ shift = 5;
+
+ if (shift > 0)
+ {
+ /* complete with transaction mode */
+ HEAD_SHIFT(shift);
+
+ if (WORD_COUNT() == 0)
+ COMPLETE_WITH_LIST4("ISOLATION LEVEL", "READ", "DEFERRABLE",
+ "NOT DEFERRABLE");
+ if (Matches1("NOT"))
+ COMPLETE_WITH_CONST("DEFERRABLE");
+ if (Matches1("ISOLATION"))
+ COMPLETE_WITH_CONST("LEVEL");
+ if (Matches2("ISOLATION", "LEVEL"))
+ COMPLETE_WITH_LIST3("READ", "REPEATABLE READ", "SERIALIZABLE");
+ if (Matches3("ISOLATION", "LEVEL", "REPEATABLE"))
+ COMPLETE_WITH_CONST("READ");
+ if (Matches3("ISOLATION", "LEVEL", "READ"))
+ COMPLETE_WITH_LIST2("UNCOMMITTED", "COMMITTED");
+ if (Matches1("READ"))
+ COMPLETE_WITH_LIST2("ONLY", "WRITE");
+ COMPLETE_WITH_CONST("");
+ }
+ }
/* SET CONSTRAINTS */
if (Matches2("SET", "CONSTRAINTS"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_constraints_with_schema,
@@ -2601,18 +2636,18 @@ psql_completion_internal(const char *text, char **previous_words,
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 --- can be inside EXPLAIN, RULE, etc */
+/* UPDATE */
/* If prev. word is UPDATE suggest a list of tables */
- if (TailMatches1("UPDATE"))
+ if (Matches1("UPDATE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables);
/* Complete UPDATE <table> with "SET" */
- if (TailMatches2("UPDATE", MatchAny))
+ if (Matches2("UPDATE", MatchAny))
COMPLETE_WITH_CONST("SET");
/* Complete UPDATE <table> SET with list of attributes */
- if (TailMatches3("UPDATE", MatchAny, "SET"))
- COMPLETE_WITH_ATTR(prev2_wd, "");
+ if (Matches3("UPDATE", MatchAny, "SET"))
+ COMPLETE_WITH_ATTR(prev2_wd);
/* UPDATE <table> SET <attr> = */
- if (TailMatches4("UPDATE", MatchAny, "SET", MatchAny))
+ if (Matches4("UPDATE", MatchAny, "SET", MatchAny))
COMPLETE_WITH_CONST("=");
/* USER MAPPING */
@@ -2671,7 +2706,7 @@ psql_completion_internal(const char *text, char **previous_words,
/* WHERE */
/* Simple case of the word before the where being the table name */
if (TailMatches2(MatchAny, "WHERE"))
- COMPLETE_WITH_ATTR(prev2_wd, "");
+ COMPLETE_WITH_ATTR(prev2_wd);
/* ... FROM ... */
/* TODO: also include SRF ? */
@@ -2844,18 +2879,14 @@ psql_completion_internal(const char *text, char **previous_words,
*/
else
{
- int i;
+ const pgsql_thing_t *ent = find_thing_entry(prev_wd);
- for (i = 0; words_after_create[i].name; i++)
+ if (ent)
{
- if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0)
- {
- if (words_after_create[i].query)
- COMPLETE_WITH_QUERY(words_after_create[i].query);
- if (words_after_create[i].squery)
- COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery);
- break;
- }
+ if (ent->query)
+ COMPLETE_WITH_QUERY(ent->query);
+ else if (ent->squery)
+ COMPLETE_WITH_SCHEMA_QUERY(*ent->squery);
}
}
@@ -3366,6 +3397,18 @@ complete_from_files(const char *text, int state)
/* HELPER FUNCTIONS */
+/*
+ * Return the index (reverse to the index of previous_words) of the tailmost
+ * (topmost in the array) appearance of w.
+ */
+static int
+find_last_index_of(char *w, char **previous_words, int len)
+{
+ int i;
+
+ for (i = 0 ; i < len && !word_matches(w, previous_words[i]) ; i++);
+ return i < len ? (len - i - 1) : 0;
+}
/*
* Make a pg_strdup copy of s and convert the case according to
@@ -3665,6 +3708,24 @@ get_guctype(const char *varname)
return guctype;
}
+/*
+ * Finds the entry in words_after_create[] that matches the word.
+ * NULL if not found.
+ */
+static const pgsql_thing_t *
+find_thing_entry(char *word)
+{
+ int i;
+
+ for (i = 0; words_after_create[i].name; i++)
+ {
+ if (pg_strcasecmp(word, words_after_create[i].name) == 0)
+ return words_after_create + i;
+ }
+
+ return NULL;
+}
+
#ifdef NOT_USED
/*
--
2.9.2
0005-Add-suggestion-for-IF-NOT-EXISTS-for-some-syntaxes.patch (text/x-patch, 14.4K) download
From 887b7c483ef7a494fb107f9a7cf7d35182f47b7b Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Thu, 15 Sep 2016 20:49:45 +0900
Subject: [PATCH 5/6] Add suggestion for IF (NOT) EXISTS for some syntaxes
Add suggestion for IF EXISTS or IF NOT EXISTS for some arbitrary
syntaxes, ALTER TABLE/ALTER FOREIGN TABLE/ALTER INDEX/
ALTER MATERIALIZED VIEW/ALTER DOMAIN DROP CONSTRAINT/ALTER SEQUENCE/
ALTER VIEW/ALTER POLICY/ALTER TABLE DROP COLUMN/
ALTER TABLE DROP CONSTRAINT/CREATE INDEX/CREATE SEQUENCE/
CREATE TABLE/CREATE VIEW/DROP INDEX/DROP (MATERIALIZED) VIEW/
DROP USER MAPPING
---
src/bin/psql/tab-complete.c | 180 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 168 insertions(+), 12 deletions(-)
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 7a880d9..3b10b85 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1074,7 +1074,9 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER TABLE */
if (Matches2("ALTER", "TABLE"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
- ADDLIST1("ALL IN TABLESPACE"));
+ ADDLIST2("ALL IN TABLESPACE", "IF EXISTS"));
+ if (HeadMatches4("ALTER", "TABLE", "IF", "EXISTS"))
+ COLLAPSE(3, 2);
/* ALTER something */
if (Matches1("ALTER"))
@@ -1177,6 +1179,14 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches5("ALTER", "FOREIGN", "DATA", "WRAPPER", MatchAny))
COMPLETE_WITH_LIST5("HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", "RENAME TO");
+ /* ALTER FOREIGN TABLE */
+ if (Matches3("ALTER", "FOREIGN", "TABLE"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_foreign_tables,
+ ADDLIST1("IF EXISTS"));
+ /* Remove optional words for further completion */
+ if (HeadMatches5("ALTER", "FOREIGN", "TABLE", "IF", "EXISTS"))
+ COLLAPSE(4, 2);
+
/* ALTER FOREIGN TABLE <name> */
if (Matches4("ALTER", "FOREIGN", "TABLE", MatchAny))
{
@@ -1191,7 +1201,11 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER INDEX */
if (Matches2("ALTER", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
- ADDLIST1("ALL IN TABLESPACE"));
+ ADDLIST2("ALL IN TABLESPACE", "IF EXISTS"));
+ /* Remove optional words for further completion */
+ if (HeadMatches4("ALTER", "INDEX", "IF", "EXISTS"))
+ COLLAPSE(3, 2);
+
/* ALTER INDEX <name> */
if (Matches3("ALTER", "INDEX", MatchAny))
COMPLETE_WITH_LIST4("OWNER TO", "RENAME TO", "SET", "RESET");
@@ -1220,7 +1234,10 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER MATERIALIZED VIEW */
if (Matches3("ALTER", "MATERIALIZED", "VIEW"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews,
- ADDLIST1("ALL IN TABLESPACE"));
+ ADDLIST2("ALL IN TABLESPACE", "IF EXISTS"));
+ /* Remove optional words for further completion */
+ if (HeadMatches5("ALTER", "MATERIALIZED", "VIEW", "IF", "EXISTS"))
+ COLLAPSE(4, 2);
/* ALTER USER,ROLE <name> */
if (Matches3("ALTER", "USER|ROLE", MatchAny) &&
@@ -1276,6 +1293,19 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP|RENAME|VALIDATE", "CONSTRAINT"))
{
completion_info_charp = prev3_wd;
+ if (word_matches("DROP", prev2_wd))
+ COMPLETE_WITH_QUERY_KW(Query_for_constraint_of_type,
+ ADDLIST1("IF EXISTS"));
+ else
+ COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
+ }
+ /* Remove optional words for further completion */
+ if (HeadMatches7("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT", "IF", "EXISTS"))
+ COLLAPSE(6, 2);
+ /* Complete constraint name again without IF EXISTS */
+ if (Matches5("ALTER", "DOMAIN", MatchAny, "DROP", "CONSTRAINT"))
+ {
+ completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_constraint_of_type);
}
/* ALTER DOMAIN <sth> RENAME */
@@ -1288,6 +1318,16 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER DOMAIN <sth> SET */
if (Matches4("ALTER", "DOMAIN", MatchAny, "SET"))
COMPLETE_WITH_LIST3("DEFAULT", "NOT NULL", "SCHEMA");
+ /* ALTER SEQUENCE */
+ if (Matches2("ALTER", "SEQUENCE"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_sequences,
+ ADDLIST1("IF EXISTS"));
+ /* Remove optional words for further completion */
+ if (HeadMatches4("ALTER", "SEQUENCE", "IF", "EXISTS"))
+ COLLAPSE(3, 2);
+ /* Complete again without IF EXISTS */
+ if (Matches2("ALTER", "SEQUENCE"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
/* ALTER SEQUENCE <name> */
if (Matches3("ALTER", "SEQUENCE", MatchAny))
{
@@ -1313,6 +1353,16 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches3("ALTER", "SYSTEM", "SET|RESET"))
COMPLETE_WITH_QUERY_KW(Query_for_list_of_alter_system_set_vars,
ADDLIST1("ALL"));
+ /* ALTER VIEW */
+ if (Matches2("ALTER", "VIEW"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views,
+ ADDLIST1("IF EXISTS"));
+ /* Remove optional words for further completion */
+ if (HeadMatches4("ALTER", "VIEW", "IF", "EXISTS"))
+ COLLAPSE(3, 2);
+ /* Complete again without IF EXISTS */
+ if (Matches2("ALTER", "VIEW"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
/* ALTER VIEW <name> */
if (Matches3("ALTER", "VIEW", MatchAny))
COMPLETE_WITH_LIST4("ALTER COLUMN", "OWNER TO", "RENAME TO",
@@ -1324,6 +1374,12 @@ psql_completion_internal(const char *text, char **previous_words,
/* ALTER POLICY <name> */
if (Matches2("ALTER", "POLICY"))
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_policies, ADDLIST1("IF EXISTS"));
+ /* Remove optional words for further completion */
+ if (Matches4("ALTER", "POLICY", "IF", "EXISTS"))
+ COLLAPSE(3, 2);
+ /* Complete again without IF EXISTS */
+ if (Matches2("ALTER", "POLICY"))
COMPLETE_WITH_QUERY(Query_for_list_of_policies);
/* ALTER POLICY <name> ON */
if (Matches3("ALTER", "POLICY", MatchAny))
@@ -1463,8 +1519,13 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST2("COLUMN", "CONSTRAINT");
/* If we have ALTER TABLE <sth> DROP COLUMN, provide list of columns */
if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
+ COMPLETE_WITH_ATTR_KW(prev3_wd, ADDLIST1("IF EXISTS"));
+ /* Remove optional words for further completion */
+ if (HeadMatches7("ALTER", "TABLE", MatchAny, "DROP", "COLUMN", "IF", "EXISTS"))
+ COLLAPSE(6, 2);
+ /* Complete again without IF EXISTS */
+ if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "COLUMN"))
COMPLETE_WITH_ATTR(prev3_wd);
-
/*
* If we have ALTER TABLE <sth> ALTER|DROP|RENAME|VALIDATE CONSTRAINT,
* provide list of constraints
@@ -1472,6 +1533,19 @@ psql_completion_internal(const char *text, char **previous_words,
if (Matches5("ALTER", "TABLE", MatchAny, "ALTER|DROP|RENAME|VALIDATE", "CONSTRAINT"))
{
completion_info_charp = prev3_wd;
+ if (word_matches("DROP", prev2_wd))
+ COMPLETE_WITH_QUERY_KW(Query_for_constraint_of_table,
+ ADDLIST1("IF EXISTS"));
+ else
+ COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
+ }
+ /* Remove IF EXISTS for further completion */
+ if (HeadMatches7("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT", "IF", "EXISTS"))
+ COLLAPSE(6, 2);
+ /* Complete again without IF EXISTS */
+ if (Matches5("ALTER", "TABLE", MatchAny, "DROP", "CONSTRAINT"))
+ {
+ completion_info_charp = prev3_wd;
COMPLETE_WITH_QUERY(Query_for_constraint_of_table);
}
/* Remove COLUMN just after ALTER */
@@ -1614,7 +1688,18 @@ psql_completion_internal(const char *text, char **previous_words,
* of attributes
*/
if (Matches5("ALTER", "TYPE", MatchAny, "ALTER|DROP|RENAME", "ATTRIBUTE"))
- COMPLETE_WITH_ATTR(prev3_wd);
+ {
+ if (word_matches("DROP", prev2_wd))
+ COMPLETE_WITH_ATTR_KW(prev3_wd, ADDLIST1("IF EXISTS"));
+ else
+ COMPLETE_WITH_ATTR(prev3_wd);
+ }
+ /* Remove IF EXISTS for further completion */
+ if (HeadMatches7("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE", "IF", "EXISTS"))
+ COLLAPSE(6, 2);
+ /* Complete again without IF EXISTS */
+ if (Matches5("ALTER", "TYPE", MatchAny, "DROP", "ATTRIBUTE"))
+ COMPLETE_WITH_ATTR(prev3_wd);
/* ALTER TYPE ALTER ATTRIBUTE <foo> */
if (Matches6("ALTER", "TYPE", MatchAny, "ALTER", "ATTRIBUTE", MatchAny))
COMPLETE_WITH_CONST("TYPE");
@@ -1762,6 +1847,13 @@ psql_completion_internal(const char *text, char **previous_words,
/* CREATE EXTENSION */
/* Complete with available extensions rather than installed ones. */
if (Matches2("CREATE", "EXTENSION"))
+ COMPLETE_WITH_QUERY_KW(Query_for_list_of_available_extensions,
+ ADDLIST1("IF NOT EXISTS"));
+ /* Remove IF NOT EXISTS for further completion*/
+ if (HeadMatches5("CREATE", "EXTENSION", "IF", "NOT", "EXISTS"))
+ COLLAPSE(3, 3);
+ /* Complete again without IF NOT EXISTS */
+ if (Matches2("CREATE", "EXTENSION"))
COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions);
/* CREATE EXTENSION <name> */
if (Matches3("CREATE", "EXTENSION", MatchAny))
@@ -1792,14 +1884,20 @@ psql_completion_internal(const char *text, char **previous_words,
/* Complete with index names as category suggestion and possible keywords */
if (Matches2("CREATE", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
- ADDLIST2("ON", "CONCURRENTLY"));
+ ADDLIST3("ON", "CONCURRENTLY", "IF NOT EXISTS"));
/* Remove CONCURRENTLY for further completion */
if (HeadMatches3("CREATE", "INDEX", "CONCURRENTLY"))
COLLAPSE(3, 1);
/* Complete with existing index names as word category suggestion */
if (Matches2("CREATE", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
- ADDLIST1("ON"));
+ ADDLIST2("ON", "IF NOT EXISTS"));
+ /* Remove IF NOT EXISTS for further completion */
+ if (HeadMatches5("CREATE", "INDEX", "IF", "NOT", "EXISTS"))
+ COLLAPSE(3, 3);
+ /* Complete again without IF NOT EXISTS */
+ if (Matches2("CREATE", "INDEX"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
/* Suggest ON just after index name */
if (Matches3("CREATE", "INDEX", MatchAnyExcept("ON")))
COMPLETE_WITH_CONST("ON");
@@ -1892,6 +1990,13 @@ psql_completion_internal(const char *text, char **previous_words,
/* CREATE SEQUENCE */
if (Matches2("CREATE", "SEQUENCE"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_sequences,
+ ADDLIST1("IF NOT EXISTS"));
+ /* Remove IF NOT EXISTS for further completion */
+ if (HeadMatches5("CREATE", "SEQUENCE", "IF", "NOT", "EXISTS"))
+ COLLAPSE(3, 3);
+ /* Complete again without IF NOT EXISTS */
+ if (Matches2("CREATE", "SEQUENCE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences);
if (Matches3("CREATE", "SEQUENCE", MatchAny))
COMPLETE_WITH_LIST8("INCREMENT BY", "MINVALUE", "MAXVALUE", "NO",
@@ -1917,6 +2022,13 @@ psql_completion_internal(const char *text, char **previous_words,
COLLAPSE(2, 1);
/* Complete CREATE TABLE with existing table names */
if (Matches2("CREATE", "TABLE"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_tables,
+ ADDLIST1("IF NOT EXISTS"));
+ /* Remove IF NOT EXIST for further completion */
+ if (HeadMatches5("CREATE", "TABLE", "IF", "NOT", "EXISTS"))
+ COLLAPSE(3, 3);
+ /* Complete again without IF NOT EXISTS */
+ if (Matches2("CREATE", "TABLE"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
/* CREATE TABLESPACE */
@@ -2001,6 +2113,16 @@ psql_completion_internal(const char *text, char **previous_words,
COMPLETE_WITH_LIST2("GROUP", "ROLE");
/* CREATE VIEW */
+ /* Complete CREATE VIEW with name */
+ if (Matches2("CREATE", "VIEW"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views,
+ ADDLIST1("IF NOT EXISTS"));
+ /* Remove IF NOT EXISTS for further completion */
+ if (HeadMatches5("CREATE", "VIEW", "IF", "NOT", "EXISTS"))
+ COLLAPSE(3, 3);
+ /* Complete again without IF NOT EXISTS */
+ if (Matches2("CREATE", "VIEW"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views);
/* Complete CREATE VIEW <name> with AS */
if (Matches3("CREATE", "VIEW", MatchAny))
COMPLETE_WITH_CONST("AS");
@@ -2080,20 +2202,43 @@ psql_completion_internal(const char *text, char **previous_words,
/* DROP INDEX */
if (Matches2("DROP", "INDEX"))
COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
- ADDLIST1("CONCURRENTLY"));
- if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
- COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
+ ADDLIST2("CONCURRENTLY", "IF EXISTS"));
+ if (Matches3("DROP", "INDEX", "CONCURRENTLY"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_indexes,
+ ADDLIST1("IF EXISTS"));
if (HeadMatches3("DROP", "INDEX", "CONCURRENTLY"))
COLLAPSE(3, 1);
+ /* Remove IF EXISTS for further completion */
+ if (HeadMatches4("DROP", "INDEX", "IF", "EXISTS"))
+ COLLAPSE(3, 2);
+ /* Complete again without IF EXISTS */
+ if (Matches2("DROP", "INDEX"))
+ COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes);
if (Matches3("DROP", "INDEX", MatchAny))
COMPLETE_WITH_LIST2("CASCADE", "RESTRICT");
+ /* DROP VIEW */
+ if (Matches2("DROP", "VIEW"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_views,
+ ADDLIST1("IF EXISTS"));
+ /* Remove IF EXISTS for further completion */
+ if (HeadMatches4("DROP", "VIEW", "IF", "EXISTS"))
+ COLLAPSE(3, 2);
+ /* Complet again without IF EXISTS */
+ if (Matches2("DROP", "VIEW"))
+ COMPLETE_THING(-1);
+
/* DROP MATERIALIZED VIEW */
if (Matches2("DROP", "MATERIALIZED"))
COMPLETE_WITH_CONST("VIEW");
- /* DROP VIEW is suggested as a general thing */
-
+ if (Matches3("DROP", "MATERIALIZED", "VIEW"))
+ COMPLETE_WITH_SCHEMA_QUERY_KW(Query_for_list_of_matviews,
+ ADDLIST1("IF EXISTS"));
+ /* Remove IF EXISTS for further completion */
+ if (HeadMatches5("DROP", "MATERIALIZED", "VIEW", "IF", "EXISTS"))
+ COLLAPSE(4, 2);
+ /* Complet again without IF EXISTS */
if (Matches3("DROP", "MATERIALIZED", "VIEW"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews);
@@ -2652,6 +2797,17 @@ psql_completion_internal(const char *text, char **previous_words,
/* USER MAPPING */
if (Matches3("ALTER|CREATE|DROP", "USER", "MAPPING"))
+ {
+ if (word_matches("DROP", prev3_wd))
+ COMPLETE_WITH_LIST2("FOR", "IF EXISTS FOR");
+ else
+ COMPLETE_WITH_CONST("FOR");
+ }
+ /* Remove IF EXISTS for further completion */
+ if (HeadMatches5("DROP", "USER", "MAPPING", "IF", "EXISTS"))
+ COLLAPSE(4, 2);
+ /* Complete again without IF EXISTS */
+ if (Matches3("DROP", "USER", "MAPPING"))
COMPLETE_WITH_CONST("FOR");
if (Matches4("CREATE", "USER", "MAPPING", "FOR"))
COMPLETE_WITH_QUERY_KW(Query_for_list_of_roles,
--
2.9.2
0006-Add-README-for-tab-completion.patch (text/x-patch, 6.3K) download
From 6d2cde0f44c880f7edc4fe3527ef02ca28248e74 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horiguchi.kyotaro@lab.ntt.co.jp>
Date: Wed, 26 Oct 2016 12:06:33 +0900
Subject: [PATCH 6/6] Add README for tab-completion.
---
src/bin/psql/README.completion | 165 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 165 insertions(+)
create mode 100644 src/bin/psql/README.completion
diff --git a/src/bin/psql/README.completion b/src/bin/psql/README.completion
new file mode 100644
index 0000000..65981e4
--- /dev/null
+++ b/src/bin/psql/README.completion
@@ -0,0 +1,165 @@
+Word completion of interactive psql
+===================================
+
+psql supports word completion on interactive input. The core function
+of the feature is psql_completion_internal in tab-complete.c. A bunch
+of macros are provided in order to make it easier to read and maintain
+the completion code. psql_completion is called with reference console
+input stored in char ** previous_words in reverse order but developers
+don't need to be aware of the detail. Most of the operations can be
+described using the provided macros.
+
+Basic structure of the completion code
+--------------------------------------
+
+The main part of the function is just a series of completion
+definitions, where the first match wins. Each definition basically is
+in the following shape.
+
+ if (*matching expression*)
+ *enumeration of words for completion, then return*
+
+The matching expression is examined against previous_words which
+contains the whole command line before the last space. The completion
+code enumerates the expected words. For example, for "CREATE <tab>"
+the word list to be matched is ["CREATE"] and the prefix for
+completion is nothing. For "CREATE INDEX i", the list is ["CREATE",
+"INDEX"] and the prefix for enumeration is "i".
+
+
+Matching expression macros
+--------------------------
+There are four types of matching expression macros.
+
+- MatchesN(word1, word2 .. , wordN)
+
+ true iff the word list is exactly the same as the paremeter.
+
+- HeadMatchesN(word1, word2 .., wordN)
+
+ true iff the first N words in the word list matches the parameter.
+
+- TailMatchesN(word1, word2 .., wordN)
+
+ true iff the last N words in the word list matches the parameter.
+
+- MidMatchesN(pos, word1, word2 .., wordN)
+
+ true iff N successive words starts from pos in the word list matches
+ the parameter. The position is 1-based.
+
+Special matching words
+----------------------
+
+A defined symbol MatchAny matches any word. If you want to match any
+of several words, multiple words concatenated by '|' can be
+used. "CREATE|UPDATE" matches any of "CREATE" and "UPDATE".
+
+
+Enumeration macros
+-----------------
+There are N types of word enumeration macros.
+
+- COMPLETE_WITH_QUERY(query), COMPLETE_WITH_QUERY_KW(query, addon)
+
+ Suggest completion words acquired using the given query. The details
+ of the query is seen in the comment for _complete_from_query(). Word
+ matching is case-sensitive.
+
+ The latter form takes an additional parameter, which should be a
+ fragment of query starts with " UNION " followed by a query string
+ which gives some additional words. For case-insensitive suggestion,
+ this could be as simple as a static query string but for
+ case-sensitive case, where the letter case of suggested words
+ follows input, ADDLISTN() macro can be used.
+
+- COMPLETE_WITH_SCHEMA_QUERY(squery),
+ COMPLETE_WITH_SCHEMA_QUERY_KW(squery, addon)
+
+ Suggest words based on a "schema query", which is a struct that
+ containing parameters. You will see the details in the comment for
+ _complete_from_query(). Word maching is case-sensitive.
+
+ Just same as COMPLETE_WITH_QUERY_KW, the latter form takes a
+ fragment query same to that for COMPLETE_WITH_QUERY_KW.
+
+- COMPLETE_WITH_LIST_CS(list)
+
+ Suggest completion words given as a string array. Word matching is
+ case-sensitive.
+
+- COMPLETE_WITH_LIST_CSN(s1, s2.. ,sN)
+
+ Shortcut for COMPLETE_WITH_LIST_CS.
+
+- COMPLETE_WITH_LIST(list)
+
+ Same as COMPLETE_WITH_LIST_CS except that word matching is
+ case-insensitive and the letter case of suggested words is
+ determined according to COMP_KEYWORD_CASE.
+
+- COMPLETE_WITH_LISTN(s1, s2.. ,sN)
+
+ Shortcut for COMPLETE_WITH_LIST.
+
+- COMPLETE_WITH_CONST(string)
+
+ Same as COMPLETE_WITH_LIST but with just one suggestion.
+
+- COMPLETE_WITH_ATTR(relation, addon)
+
+ Suggest attribute names for the given relation. Word matching is
+ case-sensitve.
+
+- COMPLETE_WITH_FUNCTION_ARG(function)
+
+ Suggest function name for the given SQL function. Word matching is
+ case-sensitve.
+
+- COMPLETE_THING(relpos)
+
+ Suggest any object name designated by the word at relpos from the
+ current word. COMPLETE_THING(-1) for "... TABLE " enumerates names
+ of all available tables.
+
+
+Additional keywords for COMPLETE_WITH(_SCHEMA)_QUERY
+----------------------------------------------------
+
+Some syntaxes need suggestion by mixture of object names and
+keywords. Object names are enumarated with
+COMPLETE_WITH(_SCHEMA)_QUERY but keywords should be added manually
+onto them. COMPLETE_WITH(_SCHEMA)_QUERY_KW takes a fragment query that
+gives keywords to be suggested with the object names. Since the
+framgent queriy is just appended to the main query so it is in the
+form of ' UNION <any sql>' that adds arbitrary number of tuples
+contain a text value. For example,
+
+" UNION ALL SELECT 'CURRENT_USER' UNION ALL SELECT 'PUBLIC'"
+
+If you want the case of the keywords to follow input, ADDLISTN() macro
+provides a fragment query containing such keywords.
+
+ADDLIST3("CURRENT_USER", "PUBLIC", "USER") for input 'c' returns a
+fragment query equivalent to the following,
+
+" UNION ALL SELECT 'current_user' UNION ALL SELECT 'public'"
+
+
+Removing "NOISE" words
+----------------------------------------------------
+
+Many syntaxes has "NOISE" words, that is, words that has no effect on
+the following completion. For example, the existence of the second
+word in "CREATE UNIQUE INDEX" makes no difference for further
+completion behavior. Removing such words makes further completion code
+simpler.
+
+COLLAPSE(s, l) removes l words starts from s from previous_words.
+
+if (Matches("CREATE", "UNIQUE", "INDEX"))
+ COLLAPSE(2, 1);
+
+After the above code, the previous_words is ["CREATE", "INDEX"] so the
+following completion definitions need not care about the removed words.
+
--
2.9.2
view thread (90+ messages) latest in thread
Message-ID: <20161031.101548.162143279.horiguchi.kyotaro@lab.ntt.co.jp>
Permalink: ../20161031.101548.162143279.horiguchi.kyotaro@lab.ntt.co.jp/
Also on: postgresql.org/message-id/20161031.101548.162143279.horiguchi.kyotaro@lab.ntt.co.jp
copy link · copy postgr.es · copy git am
reply Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: horiguchi.kyotaro@lab.ntt.co.jp, pavel.stehule@gmail.com
Subject: Re: IF (NOT) EXISTS in psql-completion
In-Reply-To: <20161031.101548.162143279.horiguchi.kyotaro@lab.ntt.co.jp>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox