On 2022/09/16 11:46, bt22kawamotok wrote:
Thanks for updating.

+        COMPLETE_WITH("UPDATE", "DELETE", "DO NOTHING");

"UPDATE" is always followed by "SET",  so why not complement it with
"UPDATE SET"?

Thanks for reviewing.
That's a good idea!
I create new patch v7.

Thanks for updating the patch!

I applied the following changes to the patch. Attached is the updated version 
of the patch.

The tab-completion code for MERGE was added in the middle of that for LOCK 
TABLE.
This would be an oversight of the commit that originally supported 
tab-completion
for MERGE. I fixed this issue.

+       else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
+                        TailMatches("MERGE", "INTO", MatchAny, 
MatchAnyExcept("AS")))
                COMPLETE_WITH("USING");

This can cause to complete "MERGE INTO <table> USING" with "USING" unexpectedly.
I fixed this issue by replacing MatchAnyExcept("AS") with 
MatchAnyExcept("USING|AS").

I added some comments.

"MERGE" was tab-completed with just after "EXPLAIN" or "EXPLAIN ANALYZE", etc.
Since "INTO" always follows "MERGE", it's better to complete with "MERGE INTO"
there. I replaced "MERGE" with "MERGE INTO" in those tab-completions.

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index f3465adb85..23f2a87991 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1669,7 +1669,7 @@ psql_completion(const char *text, int start, int end)
                "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE",
                "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", 
"EXPLAIN",
                "FETCH", "GRANT", "IMPORT FOREIGN SCHEMA", "INSERT INTO", 
"LISTEN", "LOAD", "LOCK",
-               "MERGE", "MOVE", "NOTIFY", "PREPARE",
+               "MERGE INTO", "MOVE", "NOTIFY", "PREPARE",
                "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE",
                "RESET", "REVOKE", "ROLLBACK",
                "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START",
@@ -3641,7 +3641,7 @@ psql_completion(const char *text, int start, int end)
  */
        else if (Matches("EXPLAIN"))
                COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", 
"DECLARE",
-                                         "MERGE", "EXECUTE", "ANALYZE", 
"VERBOSE");
+                                         "MERGE INTO", "EXECUTE", "ANALYZE", 
"VERBOSE");
        else if (HeadMatches("EXPLAIN", "(*") &&
                         !HeadMatches("EXPLAIN", "(*)"))
        {
@@ -3660,12 +3660,12 @@ psql_completion(const char *text, int start, int end)
        }
        else if (Matches("EXPLAIN", "ANALYZE"))
                COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", 
"DECLARE",
-                                         "MERGE", "EXECUTE", "VERBOSE");
+                                         "MERGE INTO", "EXECUTE", "VERBOSE");
        else if (Matches("EXPLAIN", "(*)") ||
                         Matches("EXPLAIN", "VERBOSE") ||
                         Matches("EXPLAIN", "ANALYZE", "VERBOSE"))
                COMPLETE_WITH("SELECT", "INSERT INTO", "DELETE FROM", "UPDATE", 
"DECLARE",
-                                         "MERGE", "EXECUTE");
+                                         "MERGE INTO", "EXECUTE");
 
 /* FETCH && MOVE */
 
@@ -4065,58 +4065,90 @@ psql_completion(const char *text, int start, int end)
        else if (HeadMatches("LOCK") && TailMatches("IN", "SHARE"))
                COMPLETE_WITH("MODE", "ROW EXCLUSIVE MODE",
                                          "UPDATE EXCLUSIVE MODE");
+
+       /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with 
"NOWAIT" */
+       else if (HeadMatches("LOCK") && TailMatches("MODE"))
+               COMPLETE_WITH("NOWAIT");
+
 /* MERGE --- can be inside EXPLAIN */
        else if (TailMatches("MERGE"))
                COMPLETE_WITH("INTO");
        else if (TailMatches("MERGE", "INTO"))
                COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_mergetargets);
+
+       /* Complete MERGE INTO <table> [[AS] <alias>] with USING */
        else if (TailMatches("MERGE", "INTO", MatchAny))
                COMPLETE_WITH("USING", "AS");
-       else if (TailMatches("MERGE", "INTO", MatchAny, "USING"))
-               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
-       /* with [AS] alias */
-       else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny))
+       else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny) ||
+                        TailMatches("MERGE", "INTO", MatchAny, 
MatchAnyExcept("USING|AS")))
                COMPLETE_WITH("USING");
-       else if (TailMatches("MERGE", "INTO", MatchAny, MatchAny))
-               COMPLETE_WITH("USING");
-       else if (TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, 
"USING"))
-               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
-       else if (TailMatches("MERGE", "INTO", MatchAny, MatchAny, "USING"))
-               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
-       /* ON */
-       else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny))
-               COMPLETE_WITH("ON");
-       else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", 
MatchAny, "AS", MatchAny))
-               COMPLETE_WITH("ON");
-       else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, 
MatchAny))
+
+       /*
+        * Complete MERGE INTO ... USING with a list of relations supporting
+        * SELECT
+        */
+       else if (TailMatches("MERGE", "INTO", MatchAny, "USING") ||
+                        TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, 
"USING") ||
+                        TailMatches("MERGE", "INTO", MatchAny, MatchAny, 
"USING"))
+               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_selectables);
+
+       /*
+        * Complete MERGE INTO <table> [[AS] <alias>] USING <relations>
+        * [[AS] alias] with ON
+        */
+       else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny) ||
+                        TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, 
"USING", MatchAny) ||
+                        TailMatches("MERGE", "INTO", MatchAny, MatchAny, 
"USING", MatchAny))
+               COMPLETE_WITH("AS", "ON");
+       else if (TailMatches("MERGE", "INTO", MatchAny, "USING", MatchAny, 
"AS", MatchAny) ||
+                        TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, 
"USING", MatchAny, "AS", MatchAny) ||
+                        TailMatches("MERGE", "INTO", MatchAny, MatchAny, 
"USING", MatchAny, "AS", MatchAny) ||
+                        TailMatches("MERGE", "INTO", MatchAny, "USING", 
MatchAny, MatchAnyExcept("ON|AS")) ||
+                        TailMatches("MERGE", "INTO", MatchAny, "AS", MatchAny, 
"USING", MatchAny, MatchAnyExcept("ON|AS")) ||
+                        TailMatches("MERGE", "INTO", MatchAny, MatchAny, 
"USING", MatchAny, MatchAnyExcept("ON|AS")))
                COMPLETE_WITH("ON");
-       /* ON condition */
+
+       /* Complete MERGE INTO ... ON with target table attributes */
        else if (TailMatches("INTO", MatchAny, "USING", MatchAny, "ON"))
                COMPLETE_WITH_ATTR(prev4_wd);
        else if (TailMatches("INTO", MatchAny, "AS", MatchAny, "USING", 
MatchAny, "AS", MatchAny, "ON"))
                COMPLETE_WITH_ATTR(prev8_wd);
        else if (TailMatches("INTO", MatchAny, MatchAny, "USING", MatchAny, 
MatchAny, "ON"))
                COMPLETE_WITH_ATTR(prev6_wd);
-       /* WHEN [NOT] MATCHED */
-       else if (TailMatches("USING", MatchAny, "ON", MatchAny))
+
+       /*
+        * Complete ... USING <relation> [[AS] alias] ON join condition
+        * (consisting of one or three words typically used) with
+        * WHEN [NOT] MATCHED
+        */
+       else if (TailMatches("USING", MatchAny, "ON", MatchAny) ||
+                        TailMatches("USING", MatchAny, "AS", MatchAny, "ON", 
MatchAny) ||
+                        TailMatches("USING", MatchAny, MatchAny, "ON", 
MatchAny) ||
+                        TailMatches("USING", MatchAny, "ON", MatchAny, 
MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
+                        TailMatches("USING", MatchAny, "AS", MatchAny, "ON", 
MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")) ||
+                        TailMatches("USING", MatchAny, MatchAny, "ON", 
MatchAny, MatchAnyExcept("WHEN"), MatchAnyExcept("WHEN")))
                COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
-       else if (TailMatches("USING", MatchAny, "AS", MatchAny, "ON", MatchAny))
-               COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
-       else if (TailMatches("USING", MatchAny, MatchAny, "ON", MatchAny))
-               COMPLETE_WITH("WHEN MATCHED", "WHEN NOT MATCHED");
-       else if (TailMatches("WHEN", "MATCHED"))
-               COMPLETE_WITH("THEN", "AND");
-       else if (TailMatches("WHEN", "NOT", "MATCHED"))
+       else if (TailMatches("USING", MatchAny, "ON", MatchAny, "WHEN") ||
+                        TailMatches("USING", MatchAny, "AS", MatchAny, "ON", 
MatchAny, "WHEN") ||
+                        TailMatches("USING", MatchAny, MatchAny, "ON", 
MatchAny, "WHEN") ||
+                        TailMatches("USING", MatchAny, "ON", MatchAny, 
MatchAny, MatchAny, "WHEN") ||
+                        TailMatches("USING", MatchAny, "AS", MatchAny, "ON", 
MatchAny, MatchAny, MatchAny, "WHEN") ||
+                        TailMatches("USING", MatchAny, MatchAny, "ON", 
MatchAny, MatchAny, MatchAny, "WHEN"))
+               COMPLETE_WITH("MATCHED", "NOT MATCHED");
+
+       /* Complete ... WHEN [NOT] MATCHED with THEN/AND */
+       else if (TailMatches("WHEN", "MATCHED") ||
+                        TailMatches("WHEN", "NOT", "MATCHED"))
                COMPLETE_WITH("THEN", "AND");
+
+       /* Complete ... WHEN MATCHED THEN with UPDATE SET/DELETE/DO NOTHING */
        else if (TailMatches("WHEN", "MATCHED", "THEN"))
-               COMPLETE_WITH("UPDATE", "DELETE");
+               COMPLETE_WITH("UPDATE SET", "DELETE", "DO NOTHING");
+
+       /* Complete ... WHEN NOT MATCHED THEN with INSERT/DO NOTHING */
        else if (TailMatches("WHEN", "NOT", "MATCHED", "THEN"))
                COMPLETE_WITH("INSERT", "DO NOTHING");
 
-       /* Complete LOCK [TABLE] [ONLY] <table> [IN lockmode MODE] with 
"NOWAIT" */
-       else if (HeadMatches("LOCK") && TailMatches("MODE"))
-               COMPLETE_WITH("NOWAIT");
-
 /* NOTIFY --- can be inside EXPLAIN, RULE, etc */
        else if (TailMatches("NOTIFY"))
                COMPLETE_WITH_QUERY(Query_for_list_of_channels);

Reply via email to