Rework tab completion of COPY and \copy in psql
authorMichael Paquier <michael@paquier.xyz>
Tue, 21 Jul 2020 03:05:07 +0000 (12:05 +0900)
committerMichael Paquier <michael@paquier.xyz>
Tue, 21 Jul 2020 03:05:07 +0000 (12:05 +0900)
This corrects and simplifies $subject in a number of ways:
- Remove from the completion the pre-9.0 grammar still supported for
compatibility purposes.  This simplifies the code, and allows to extend
it more easily with new patterns.
- Add completion for the options of FORMAT within a WITH clause.
- Complete WHERE and WITH clauses correctly depending on if TO or FROM
are used, WHERE being only available with COPY FROM.

Author: Vignesh C, Michael Paquier
Reviewed-by: Ahsan Hadi
Discussion: https://postgr.es/m/CALDaNm3zWr=OmxeNqOqfT=uZTSdam_j-gkX94CL8eTNfgUtf6A@mail.gmail.com

src/bin/psql/tab-complete.c

index eb018854a5c5594987458f0b303cb9beea56afa1..8b735476ade43d3e2fed66c6a181fef3a7b63428 100644 (file)
@@ -2316,19 +2316,14 @@ psql_completion(const char *text, int start, int end)
        else if (Matches("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 (Matches("COPY", "BINARY"))
-               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
-       /* If we have COPY (, complete it with legal commands */
+       /* Complete COPY ( with legal query commands */
        else if (Matches("COPY|\\copy", "("))
                COMPLETE_WITH("SELECT", "TABLE", "VALUES", "INSERT", "UPDATE", "DELETE", "WITH");
-       /* If we have COPY [BINARY] <sth>, complete it with "TO" or "FROM" */
-       else if (Matches("COPY|\\copy", MatchAny) ||
-                        Matches("COPY", "BINARY", MatchAny))
+       /* Complete COPY <sth> */
+       else if (Matches("COPY|\\copy", MatchAny))
                COMPLETE_WITH("FROM", "TO");
-       /* If we have COPY [BINARY] <sth> FROM|TO, complete with filename */
-       else if (Matches("COPY", MatchAny, "FROM|TO") ||
-                        Matches("COPY", "BINARY", MatchAny, "FROM|TO"))
+       /* Complete COPY <sth> FROM|TO with filename */
+       else if (Matches("COPY", MatchAny, "FROM|TO"))
        {
                completion_charp = "";
                completion_force_quote = true;  /* COPY requires quoted filename */
@@ -2340,17 +2335,28 @@ psql_completion(const char *text, int start, int end)
                completion_force_quote = false;
                matches = rl_completion_matches(text, complete_from_files);
        }
-       /* Offer options after COPY [BINARY] <sth> FROM|TO filename */
-       else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny) ||
-                        Matches("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny))
-               COMPLETE_WITH("BINARY", "DELIMITER", "NULL", "CSV",
-                                         "ENCODING");
-
-       /* Offer options after COPY [BINARY] <sth> FROM|TO filename CSV */
-       else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "CSV") ||
-                        Matches("COPY", "BINARY", MatchAny, "FROM|TO", MatchAny, "CSV"))
-               COMPLETE_WITH("HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE",
-                                         "FORCE NOT NULL");
+
+       /* Complete COPY <sth> TO <sth> */
+       else if (Matches("COPY|\\copy", MatchAny, "TO", MatchAny))
+               COMPLETE_WITH("WITH (");
+
+       /* Complete COPY <sth> FROM <sth> */
+       else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny))
+               COMPLETE_WITH("WITH (", "WHERE");
+
+       /* Complete COPY <sth> FROM|TO filename WITH ( */
+       else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "("))
+               COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL",
+                                         "HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE",
+                                         "FORCE_NOT_NULL", "FORCE_NULL", "ENCODING");
+
+       /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
+       else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "FORMAT"))
+               COMPLETE_WITH("binary", "csv", "text");
+
+       /* Complete COPY <sth> FROM <sth> WITH (<options>) */
+       else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny, "WITH", MatchAny))
+               COMPLETE_WITH("WHERE");
 
        /* CREATE ACCESS METHOD */
        /* Complete "CREATE ACCESS METHOD <name>" */