On Tue, Oct 26, 2010 at 11:55:07AM +0900, Itagaki Takahiro wrote:
> On Tue, Oct 26, 2010 at 11:34 AM, David Fetter <da...@fetter.org> wrote:
> >> Do we need to 'add' it?
> > Possibly.  My understanding is that it couldn't really replace it.
> 
> Ah, I see.  I was wrong.  We can have modification privileges for
> views even if they have no INSTEAD OF triggers.

Right.

> So, I think your original patch is the best solution.  We could use
> has_table_privilege() additionally, but we need to consider any
> other places if we use it.  For example, DROP privileges, etc.

That seems like a matter for a separate patch.  Looking this over, I
found I'd created a query that can never get used, so please find
enclosed the next version of the patch :)

Cheers,
David.
-- 
David Fetter <da...@fetter.org> http://fetter.org/
Phone: +1 415 235 3778  AIM: dfetter666  Yahoo!: dfetter
Skype: davidfetter      XMPP: david.fet...@gmail.com
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
***************
*** 303,308 **** static const SchemaQuery Query_for_list_of_tables = {
--- 303,359 ----
        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) = t.tgtype))",
+       /* 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_deleteables = {
+       /* 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) = t.tgtype))",
+       /* 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_updateables = {
+       /* 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) = t.tgtype))",
+       /* 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",
***************
*** 333,338 **** static const SchemaQuery Query_for_list_of_tsv = {
--- 384,404 ----
        NULL
  };
  
+ static const SchemaQuery Query_for_list_of_tv = {
+       /* catname */
+       "pg_catalog.pg_class c",
+       /* selcondition */
+       "c.relkind IN ('r', 'v')",
+       /* 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_views = {
        /* catname */
        "pg_catalog.pg_class c",
***************
*** 630,636 **** psql_completion(char *text, int start, int end)
                           *prev2_wd,
                           *prev3_wd,
                           *prev4_wd,
!                          *prev5_wd;
  
        static const char *const sql_commands[] = {
                "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", 
"CLUSTER",
--- 696,703 ----
                           *prev2_wd,
                           *prev3_wd,
                           *prev4_wd,
!                          *prev5_wd,
!                          *prev6_wd;
  
        static const char *const sql_commands[] = {
                "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", 
"CLUSTER",
***************
*** 669,675 **** psql_completion(char *text, int start, int end)
        completion_info_charp2 = NULL;
  
        /*
!        * Scan the input line before our current position for the last five
         * words. According to those we'll make some smart decisions on what the
         * user is probably intending to type. TODO: Use strtokx() to do this.
         */
--- 736,742 ----
        completion_info_charp2 = NULL;
  
        /*
!        * Scan the input line before our current position for the last six
         * words. According to those we'll make some smart decisions on what the
         * user is probably intending to type. TODO: Use strtokx() to do this.
         */
***************
*** 678,683 **** psql_completion(char *text, int start, int end)
--- 745,751 ----
        prev3_wd = previous_word(start, 2);
        prev4_wd = previous_word(start, 3);
        prev5_wd = previous_word(start, 4);
+       prev6_wd = previous_word(start, 5);
  
        /* If a backslash command was started, continue */
        if (text[0] == '\\')
***************
*** 965,978 **** psql_completion(char *text, int start, int end)
                COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
        }
  
-       /*
-        * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
-        */
-       else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
-                        pg_strcasecmp(prev3_wd, "TRIGGER") == 0 &&
-                        pg_strcasecmp(prev_wd, "ON") == 0)
-               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
- 
        /* ALTER TRIGGER <name> ON <name> */
        else if (pg_strcasecmp(prev4_wd, "TRIGGER") == 0 &&
                         pg_strcasecmp(prev2_wd, "ON") == 0)
--- 1033,1038 ----
***************
*** 1579,1585 **** psql_completion(char *text, int start, int end)
        else if (pg_strcasecmp(prev4_wd, "AS") == 0 &&
                         pg_strcasecmp(prev3_wd, "ON") == 0 &&
                         pg_strcasecmp(prev_wd, "TO") == 0)
!               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
  
  /* CREATE SERVER <name> */
        else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
--- 1639,1645 ----
        else if (pg_strcasecmp(prev4_wd, "AS") == 0 &&
                         pg_strcasecmp(prev3_wd, "ON") == 0 &&
                         pg_strcasecmp(prev_wd, "TO") == 0)
!               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tv, NULL);
  
  /* CREATE SERVER <name> */
        else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
***************
*** 1641,1655 **** psql_completion(char *text, int start, int end)
                         pg_strcasecmp(prev2_wd, "TRIGGER") == 0)
        {
                static const char *const list_CREATETRIGGER[] =
!               {"BEFORE", "AFTER", NULL};
  
                COMPLETE_WITH_LIST(list_CREATETRIGGER);
        }
        /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
!       else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
                         pg_strcasecmp(prev3_wd, "TRIGGER") == 0 &&
                         (pg_strcasecmp(prev_wd, "BEFORE") == 0 ||
!                         pg_strcasecmp(prev_wd, "AFTER") == 0))
        {
                static const char *const list_CREATETRIGGER_EVENTS[] =
                {"INSERT", "DELETE", "UPDATE", "TRUNCATE", NULL};
--- 1701,1720 ----
                         pg_strcasecmp(prev2_wd, "TRIGGER") == 0)
        {
                static const char *const list_CREATETRIGGER[] =
!               {"BEFORE", "AFTER", "INSTEAD OF", NULL};
  
                COMPLETE_WITH_LIST(list_CREATETRIGGER);
        }
        /* complete CREATE TRIGGER <name> BEFORE,AFTER with an event */
!       else if ((pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
                         pg_strcasecmp(prev3_wd, "TRIGGER") == 0 &&
                         (pg_strcasecmp(prev_wd, "BEFORE") == 0 ||
!                         pg_strcasecmp(prev_wd, "AFTER") == 0)) ||
!                       (pg_strcasecmp(prev5_wd, "CREATE") == 0 &&
!                        pg_strcasecmp(prev4_wd, "TRIGGER") == 0 &&
!                        pg_strcasecmp(prev3_wd, "INSTEAD") == 0 &&
!                        pg_strcasecmp(prev2_wd, "OF") == 0))
! 
        {
                static const char *const list_CREATETRIGGER_EVENTS[] =
                {"INSERT", "DELETE", "UPDATE", "TRUNCATE", NULL};
***************
*** 1672,1682 **** psql_completion(char *text, int start, int end)
         * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
         * tables
         */
!       else if (pg_strcasecmp(prev5_wd, "TRIGGER") == 0 &&
                         (pg_strcasecmp(prev3_wd, "BEFORE") == 0 ||
!                         pg_strcasecmp(prev3_wd, "AFTER") == 0) &&
                         pg_strcasecmp(prev_wd, "ON") == 0)
!               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
        /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
        else if (pg_strcasecmp(prev_wd, "EXECUTE") == 0)
                COMPLETE_WITH_CONST("PROCEDURE");
--- 1737,1750 ----
         * complete CREATE TRIGGER <name> BEFORE,AFTER event ON with a list of
         * tables
         */
!       else if ((pg_strcasecmp(prev5_wd, "TRIGGER") == 0 &&
                         (pg_strcasecmp(prev3_wd, "BEFORE") == 0 ||
!                         pg_strcasecmp(prev3_wd, "AFTER") == 0)) ||
!                       (pg_strcasecmp(prev6_wd, "TRIGGER") == 0 &&
!                        pg_strcasecmp(prev4_wd, "INSTEAD") == 0 &&
!                        pg_strcasecmp(prev3_wd, "OF") == 0) &&
                         pg_strcasecmp(prev_wd, "ON") == 0)
!               COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tv, NULL);
        /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */
        else if (pg_strcasecmp(prev_wd, "EXECUTE") == 0)
                COMPLETE_WITH_CONST("PROCEDURE");
***************
*** 1764,1770 **** 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 DELETE FROM <table> */
        else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 &&
                         pg_strcasecmp(prev2_wd, "FROM") == 0)
--- 1832,1838 ----
        /* 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_deleteables, NULL);
        /* Complete DELETE FROM <table> */
        else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 &&
                         pg_strcasecmp(prev2_wd, "FROM") == 0)
***************
*** 2052,2058 **** 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 "INSERT INTO <table> (" with attribute names */
        else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 &&
                         pg_strcasecmp(prev3_wd, "INTO") == 0 &&
--- 2120,2126 ----
        /* 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_insertables, NULL);
        /* Complete "INSERT INTO <table> (" with attribute names */
        else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 &&
                         pg_strcasecmp(prev3_wd, "INTO") == 0 &&
***************
*** 2409,2415 **** 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 UPDATE <table> with "SET" */
        else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0)
                COMPLETE_WITH_CONST("SET");
--- 2477,2483 ----
  /* 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_updateables, NULL);
        /* Complete UPDATE <table> with "SET" */
        else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0)
                COMPLETE_WITH_CONST("SET");
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to