]> granicus.if.org Git - postgresql/commitdiff
Improve tab-completion of DROP and ALTER ENABLE/DISABLE on triggers and rules.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 23 Jun 2014 20:47:39 +0000 (23:47 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 23 Jun 2014 20:56:20 +0000 (23:56 +0300)
At "DROP RULE/TRIGGER triggername ON ...", tab-complete tables that have
a rule/trigger with that name.

At "ALTER TABLE tablename ENABLE/DISABLE TRIGGER/RULE ...", tab-complete to
rules/triggers on that table. Previously, we would tab-complete to all
rules or triggers, not just those that are on that table.

Also, filter out internal RI triggers from the list. You can't DROP them,
and enabling/disabling them is such a rare (and dangerous) operation that
it seems better to hide them.

Andreas Karlsson, reviewed by Ian Barwick.

src/bin/psql/tab-complete.c

index 3bb727f05c92db12c495f22b25782c655949c6a1..be5c3c5f4500bc97d1158a60326021b4c347b2cc 100644 (file)
@@ -625,6 +625,14 @@ static const SchemaQuery Query_for_list_of_matviews = {
 "       (SELECT conrelid FROM pg_catalog.pg_constraint "\
 "         WHERE pg_catalog.quote_ident(conname)='%s')"
 
+/* the silly-looking length condition is just to eat up the current word */
+#define Query_for_rule_of_table \
+"SELECT pg_catalog.quote_ident(rulename) "\
+"  FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\
+" WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\
+"       and pg_catalog.quote_ident(c1.relname)='%s'"\
+"       and pg_catalog.pg_table_is_visible(c1.oid)"
+
 /* the silly-looking length condition is just to eat up the current word */
 #define Query_for_list_of_tables_for_rule \
 "SELECT pg_catalog.quote_ident(relname) "\
@@ -634,6 +642,15 @@ static const SchemaQuery Query_for_list_of_matviews = {
 "       (SELECT ev_class FROM pg_catalog.pg_rewrite "\
 "         WHERE pg_catalog.quote_ident(rulename)='%s')"
 
+/* the silly-looking length condition is just to eat up the current word */
+#define Query_for_trigger_of_table \
+"SELECT pg_catalog.quote_ident(tgname) "\
+"  FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\
+" WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\
+"       and pg_catalog.quote_ident(c1.relname)='%s'"\
+"       and pg_catalog.pg_table_is_visible(c1.oid)"\
+"       and not tgisinternal"
+
 /* the silly-looking length condition is just to eat up the current word */
 #define Query_for_list_of_tables_for_trigger \
 "SELECT pg_catalog.quote_ident(relname) "\
@@ -774,7 +791,7 @@ static const pgsql_thing_t words_after_create[] = {
        {"TEMP", NULL, NULL, THING_NO_DROP},            /* for CREATE TEMP TABLE ... */
        {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW},
        {"TEXT SEARCH", NULL, NULL},
-       {"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s'"},
+       {"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s' AND NOT tgisinternal"},
        {"TYPE", NULL, &Query_for_list_of_datatypes},
        {"UNIQUE", NULL, NULL, THING_NO_DROP},          /* for CREATE UNIQUE INDEX ... */
        {"UNLOGGED", NULL, NULL, THING_NO_DROP},        /* for CREATE UNLOGGED TABLE
@@ -1409,6 +1426,38 @@ psql_completion(const char *text, int start, int end)
 
                COMPLETE_WITH_LIST(list_ALTERENABLE2);
        }
+       else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
+                        pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
+                        pg_strcasecmp(prev2_wd, "ENABLE") == 0 &&
+                        pg_strcasecmp(prev_wd, "RULE") == 0)
+       {
+               completion_info_charp = prev3_wd;
+               COMPLETE_WITH_QUERY(Query_for_rule_of_table);
+       }
+       else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 &&
+                        pg_strcasecmp(prev5_wd, "TABLE") == 0 &&
+                        pg_strcasecmp(prev3_wd, "ENABLE") == 0 &&
+                        pg_strcasecmp(prev_wd, "RULE") == 0)
+       {
+               completion_info_charp = prev4_wd;
+               COMPLETE_WITH_QUERY(Query_for_rule_of_table);
+       }
+       else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
+                        pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
+                        pg_strcasecmp(prev2_wd, "ENABLE") == 0 &&
+                        pg_strcasecmp(prev_wd, "TRIGGER") == 0)
+       {
+               completion_info_charp = prev3_wd;
+               COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
+       }
+       else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 &&
+                        pg_strcasecmp(prev5_wd, "TABLE") == 0 &&
+                        pg_strcasecmp(prev3_wd, "ENABLE") == 0 &&
+                        pg_strcasecmp(prev_wd, "TRIGGER") == 0)
+       {
+               completion_info_charp = prev4_wd;
+               COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
+       }
        /* ALTER TABLE xxx INHERIT */
        else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
                         pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
@@ -1424,6 +1473,7 @@ psql_completion(const char *text, int start, int end)
        {
                COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, "");
        }
+       /* ALTER TABLE xxx DISABLE */
        else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
                         pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
                         pg_strcasecmp(prev_wd, "DISABLE") == 0)
@@ -1433,6 +1483,22 @@ psql_completion(const char *text, int start, int end)
 
                COMPLETE_WITH_LIST(list_ALTERDISABLE);
        }
+       else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
+                        pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
+                        pg_strcasecmp(prev2_wd, "DISABLE") == 0 &&
+                        pg_strcasecmp(prev_wd, "RULE") == 0)
+       {
+               completion_info_charp = prev3_wd;
+               COMPLETE_WITH_QUERY(Query_for_rule_of_table);
+       }
+       else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
+                        pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
+                        pg_strcasecmp(prev2_wd, "DISABLE") == 0 &&
+                        pg_strcasecmp(prev_wd, "TRIGGER") == 0)
+       {
+               completion_info_charp = prev3_wd;
+               COMPLETE_WITH_QUERY(Query_for_trigger_of_table);
+       }
 
        /* ALTER TABLE xxx ALTER */
        else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
@@ -2587,6 +2653,29 @@ psql_completion(const char *text, int start, int end)
                COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH);
        }
 
+       /* DROP TRIGGER */
+       else if (pg_strcasecmp(prev3_wd, "DROP") == 0 &&
+                        pg_strcasecmp(prev2_wd, "TRIGGER") == 0)
+       {
+               COMPLETE_WITH_CONST("ON");
+       }
+       else if (pg_strcasecmp(prev4_wd, "DROP") == 0 &&
+                        pg_strcasecmp(prev3_wd, "TRIGGER") == 0 &&
+                        pg_strcasecmp(prev_wd, "ON") == 0)
+       {
+               completion_info_charp = prev2_wd;
+               COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
+       }
+       else if (pg_strcasecmp(prev5_wd, "DROP") == 0 &&
+                        pg_strcasecmp(prev4_wd, "TRIGGER") == 0 &&
+                        pg_strcasecmp(prev2_wd, "ON") == 0)
+       {
+               static const char *const list_DROPCR[] =
+               {"CASCADE", "RESTRICT", NULL};
+
+               COMPLETE_WITH_LIST(list_DROPCR);
+       }
+
        /* DROP EVENT TRIGGER */
        else if (pg_strcasecmp(prev2_wd, "DROP") == 0 &&
                         pg_strcasecmp(prev_wd, "EVENT") == 0)
@@ -2600,6 +2689,29 @@ psql_completion(const char *text, int start, int end)
                COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers);
        }
 
+       /* DROP RULE */
+       else if (pg_strcasecmp(prev3_wd, "DROP") == 0 &&
+                        pg_strcasecmp(prev2_wd, "RULE") == 0)
+       {
+               COMPLETE_WITH_CONST("ON");
+       }
+       else if (pg_strcasecmp(prev4_wd, "DROP") == 0 &&
+                        pg_strcasecmp(prev3_wd, "RULE") == 0 &&
+                        pg_strcasecmp(prev_wd, "ON") == 0)
+       {
+               completion_info_charp = prev2_wd;
+               COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule);
+       }
+       else if (pg_strcasecmp(prev5_wd, "DROP") == 0 &&
+                        pg_strcasecmp(prev4_wd, "RULE") == 0 &&
+                        pg_strcasecmp(prev2_wd, "ON") == 0)
+       {
+               static const char *const list_DROPCR[] =
+               {"CASCADE", "RESTRICT", NULL};
+
+               COMPLETE_WITH_LIST(list_DROPCR);
+       }
+
 /* EXECUTE, but not EXECUTE embedded in other commands */
        else if (pg_strcasecmp(prev_wd, "EXECUTE") == 0 &&
                         prev2_wd[0] == '\0')