From 9878e295dc937c664367875dc001b7503df057f1 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Mon, 13 Dec 2010 22:37:55 -0500 Subject: [PATCH] Improved tab completion for views with triggers. Allow INSERT INTO, UPDATE, and DELETE FROM to be completed with either the name of a table (as before) or the name of a view with an appropriate INSTEAD OF rule. Along the way, allow CREATE TRIGGER to be completed with INSTEAD OF, as well as BEFORE and AFTER. David Fetter, reviewed by Itagaki Takahiro --- src/bin/psql/tab-complete.c | 59 ++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 4c468a858c..c88d671f40 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -303,6 +303,57 @@ static const SchemaQuery Query_for_list_of_tables = { NULL }; +/* The bit masks for the following three functions come from + * src/include/catalog/pg_trigger.h. + */ +static const SchemaQuery Query_for_list_of_insertables = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "(c.relkind = 'r' OR (c.relkind = 'v' AND c.relhastriggers AND EXISTS " + "(SELECT 1 FROM pg_catalog.pg_trigger t WHERE t.tgrelid = c.oid AND t.tgtype & (1 << 2) <> 0)))", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_deletables = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "(c.relkind = 'r' OR (c.relkind = 'v' AND c.relhastriggers AND EXISTS " + "(SELECT 1 FROM pg_catalog.pg_trigger t WHERE t.tgrelid = c.oid AND t.tgtype & (1 << 3) <> 0)))", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_updatables = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "(c.relkind = 'r' OR (c.relkind = 'v' AND c.relhastriggers AND EXISTS " + "(SELECT 1 FROM pg_catalog.pg_trigger t WHERE t.tgrelid = c.oid AND t.tgtype & (1 << 4) <> 0)))", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + static const SchemaQuery Query_for_list_of_tisv = { /* catname */ "pg_catalog.pg_class c", @@ -1655,7 +1706,7 @@ psql_completion(char *text, int start, int end) pg_strcasecmp(prev2_wd, "TRIGGER") == 0) { static const char *const list_CREATETRIGGER[] = - {"BEFORE", "AFTER", NULL}; + {"BEFORE", "AFTER", "INSTEAD OF", NULL}; COMPLETE_WITH_LIST(list_CREATETRIGGER); } @@ -1778,7 +1829,7 @@ psql_completion(char *text, int start, int end) /* Complete DELETE FROM with a list of tables */ else if (pg_strcasecmp(prev2_wd, "DELETE") == 0 && pg_strcasecmp(prev_wd, "FROM") == 0) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_deletables, NULL); /* Complete DELETE FROM */ else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 && pg_strcasecmp(prev2_wd, "FROM") == 0) @@ -2066,7 +2117,7 @@ psql_completion(char *text, int start, int end) /* Complete INSERT INTO with table names */ else if (pg_strcasecmp(prev2_wd, "INSERT") == 0 && pg_strcasecmp(prev_wd, "INTO") == 0) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_insertables, NULL); /* Complete "INSERT INTO
(" with attribute names */ else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 && pg_strcasecmp(prev3_wd, "INTO") == 0 && @@ -2423,7 +2474,7 @@ psql_completion(char *text, int start, int end) /* UPDATE */ /* If prev. word is UPDATE suggest a list of tables */ else if (pg_strcasecmp(prev_wd, "UPDATE") == 0) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); /* Complete UPDATE
with "SET" */ else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0) COMPLETE_WITH_CONST("SET");