Add more tab completion for CREATE TABLE in psql
authorMichael Paquier <michael@paquier.xyz>
Thu, 20 Dec 2018 05:24:42 +0000 (14:24 +0900)
committerMichael Paquier <michael@paquier.xyz>
Thu, 20 Dec 2018 05:29:15 +0000 (14:29 +0900)
The following completion patterns are added:
- CREATE TABLE <name> with '(', OF or PARTITION OF.
- CREATE TABLE <name> OF with list of composite types.
- CREATE TABLE name (...) with PARTITION OF, WITH, TABLESPACE, ON
COMMIT (depending on the presence of a temporary table).
- CREATE TABLE ON COMMIT with actions (only for temporary tables).

Author: Dagfinn Ilmari MannsÃ¥ker
Discussion: https://postgr.es/m/d8j1s77kdbb.fsf@dalvik.ping.uio.no

src/bin/psql/tab-complete.c

index fa44b2820b52e76819bb6378ae125e4aa42f70e9..5ba6ffba8c6c2ac66041a2953d434fe833833b74 100644 (file)
@@ -344,6 +344,18 @@ static const SchemaQuery Query_for_list_of_datatypes = {
    .qualresult = "pg_catalog.quote_ident(t.typname)",
 };
 
+static const SchemaQuery Query_for_list_of_composite_datatypes = {
+   .catname = "pg_catalog.pg_type t",
+   /* selcondition --- only get composite types */
+   .selcondition = "(SELECT c.relkind = " CppAsString2(RELKIND_COMPOSITE_TYPE)
+   " FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid) "
+   "AND t.typname !~ '^_'",
+   .viscondition = "pg_catalog.pg_type_is_visible(t.oid)",
+   .namespace = "t.typnamespace",
+   .result = "pg_catalog.format_type(t.oid, NULL)",
+   .qualresult = "pg_catalog.quote_ident(t.typname)",
+};
+
 static const SchemaQuery Query_for_list_of_domains = {
    .catname = "pg_catalog.pg_type t",
    .selcondition = "t.typtype = 'd'",
@@ -2412,6 +2424,24 @@ psql_completion(const char *text, int start, int end)
    /* Limited completion support for partition bound specification */
    else if (TailMatches("PARTITION", "OF", MatchAny))
        COMPLETE_WITH("FOR VALUES", "DEFAULT");
+   /* Complete CREATE TABLE <name> with '(', OF or PARTITION OF */
+   else if (TailMatches("CREATE", "TABLE", MatchAny) ||
+            TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny))
+       COMPLETE_WITH("(", "OF", "PARTITION OF");
+   /* Complete CREATE TABLE <name> OF with list of composite types */
+   else if (TailMatches("CREATE", "TABLE", MatchAny, "OF") ||
+            TailMatches("CREATE", "TEMP|TEMPORARY|UNLOGGED", "TABLE", MatchAny, "OF"))
+       COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_composite_datatypes, NULL);
+   /* Complete CREATE TABLE name (...) with supported options */
+   else if (TailMatches("CREATE", "TABLE", MatchAny, "(*)") ||
+            TailMatches("CREATE", "UNLOGGED", "TABLE", MatchAny, "(*)"))
+       COMPLETE_WITH("INHERITS (", "PARTITION BY", "TABLESPACE", "WITH (");
+   else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)"))
+       COMPLETE_WITH("INHERITS (", "ON COMMIT", "PARTITION BY",
+                     "TABLESPACE", "WITH (");
+   /* Complete CREATE TABLE ON COMMIT with actions */
+   else if (TailMatches("CREATE", "TEMP|TEMPORARY", "TABLE", MatchAny, "(*)", "ON", "COMMIT"))
+       COMPLETE_WITH("DELETE ROWS", "DROP", "PRESERVE ROWS");
 
 /* CREATE TABLESPACE */
    else if (Matches("CREATE", "TABLESPACE", MatchAny))