Add tab completion for CREATE SCHEMA in psql
authorMichael Paquier <[email protected]>
Fri, 30 Jun 2023 01:28:08 +0000 (10:28 +0900)
committerMichael Paquier <[email protected]>
Fri, 30 Jun 2023 01:28:08 +0000 (10:28 +0900)
The following patterns are added for CREATE SCHEMA:
- AUTHORIZATION, without a schema name or after a schema name.
- Possible list of owner roles after AUTHORIZATION.
- CREATE and GRANT within the supported set of commands.
- Correct object types supported in an embedded CREATE SCHEMA command.

While on it, this commit adjusts the completion done after CREATE
UNLOGGED:
- Addition of SEQUENCE.
- Avoid suggesting MATERIALIZED VIEW in CREATE TABLE.

Author: Dagfinn Ilmari MannsÃ¥ker
Reviewed-by: Suraj Khamkar, Michael Paquier
Discussion: https://postgr.es/m/[email protected]

src/bin/psql/tab-complete.c

index 677847e434e423023eab3e8ebf2e901e4ce73617..935bb9bd955a8448c8d19bd900238cf801513e34 100644 (file)
@@ -1031,9 +1031,13 @@ static const SchemaQuery Query_for_trigger_of_table = {
 "   FROM pg_catalog.pg_roles "\
 "  WHERE rolname LIKE '%s'"
 
+/* add these to Query_for_list_of_roles in OWNER contexts */
+#define Keywords_for_list_of_owner_roles \
+"CURRENT_ROLE", "CURRENT_USER", "SESSION_USER"
+
 /* add these to Query_for_list_of_roles in GRANT contexts */
 #define Keywords_for_list_of_grant_roles \
-"PUBLIC", "CURRENT_ROLE", "CURRENT_USER", "SESSION_USER"
+Keywords_for_list_of_owner_roles, "PUBLIC"
 
 #define Query_for_all_table_constraints \
 "SELECT conname "\
@@ -1785,8 +1789,15 @@ psql_completion(const char *text, int start, int end)
 /* CREATE */
    /* complete with something you can create */
    else if (TailMatches("CREATE"))
-       matches = rl_completion_matches(text, create_command_generator);
-
+   {
+       /* only some object types can be created as part of CREATE SCHEMA */
+       if (HeadMatches("CREATE", "SCHEMA"))
+           COMPLETE_WITH("TABLE", "VIEW", "INDEX", "SEQUENCE", "TRIGGER",
+           /* for INDEX and TABLE/SEQUENCE, respectively */
+                         "UNIQUE", "UNLOGGED");
+       else
+           matches = rl_completion_matches(text, create_command_generator);
+   }
    /* complete with something you can create or replace */
    else if (TailMatches("CREATE", "OR", "REPLACE"))
        COMPLETE_WITH("FUNCTION", "PROCEDURE", "LANGUAGE", "RULE", "VIEW",
@@ -3154,6 +3165,20 @@ psql_completion(const char *text, int start, int end)
    else if (TailMatches("AS", "ON", "SELECT|UPDATE|INSERT|DELETE", "TO"))
        COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables);
 
+/* CREATE SCHEMA [ <name> ] [ AUTHORIZATION ] */
+   else if (Matches("CREATE", "SCHEMA"))
+       COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_schemas,
+                                "AUTHORIZATION");
+   else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION") ||
+            Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION"))
+       COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
+                                Keywords_for_list_of_owner_roles);
+   else if (Matches("CREATE", "SCHEMA", "AUTHORIZATION", MatchAny) ||
+            Matches("CREATE", "SCHEMA", MatchAny, "AUTHORIZATION", MatchAny))
+       COMPLETE_WITH("CREATE", "GRANT");
+   else if (Matches("CREATE", "SCHEMA", MatchAny))
+       COMPLETE_WITH("AUTHORIZATION", "CREATE", "GRANT");
+
 /* CREATE SEQUENCE --- is allowed inside CREATE SCHEMA, so use TailMatches */
    else if (TailMatches("CREATE", "SEQUENCE", MatchAny) ||
             TailMatches("CREATE", "TEMP|TEMPORARY", "SEQUENCE", MatchAny))
@@ -3185,9 +3210,15 @@ psql_completion(const char *text, int start, int end)
    /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
    else if (TailMatches("CREATE", "TEMP|TEMPORARY"))
        COMPLETE_WITH("SEQUENCE", "TABLE", "VIEW");
-   /* Complete "CREATE UNLOGGED" with TABLE or MATVIEW */
+   /* Complete "CREATE UNLOGGED" with TABLE, SEQUENCE or MATVIEW */
    else if (TailMatches("CREATE", "UNLOGGED"))
-       COMPLETE_WITH("TABLE", "MATERIALIZED VIEW");
+   {
+       /* but not MATVIEW in CREATE SCHEMA */
+       if (HeadMatches("CREATE", "SCHEMA"))
+           COMPLETE_WITH("TABLE", "SEQUENCE");
+       else
+           COMPLETE_WITH("TABLE", "SEQUENCE", "MATERIALIZED VIEW");
+   }
    /* Complete PARTITION BY with RANGE ( or LIST ( or ... */
    else if (TailMatches("PARTITION", "BY"))
        COMPLETE_WITH("RANGE (", "LIST (", "HASH (");
@@ -4263,9 +4294,7 @@ psql_completion(const char *text, int start, int end)
 /* OWNER TO  - complete with available roles */
    else if (TailMatches("OWNER", "TO"))
        COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
-                                "CURRENT_ROLE",
-                                "CURRENT_USER",
-                                "SESSION_USER");
+                                Keywords_for_list_of_owner_roles);
 
 /* ORDER BY */
    else if (TailMatches("FROM", MatchAny, "ORDER"))