]> granicus.if.org Git - postgresql/commitdiff
Code review for GRANT CONNECT patch. Spell the privilege as CONNECT not
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 30 Apr 2006 21:15:33 +0000 (21:15 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 30 Apr 2006 21:15:33 +0000 (21:15 +0000)
CONNECTION, fix a number of places that were missed (eg pg_dump support),
avoid executing an extra search of pg_database during startup.

12 files changed:
doc/src/sgml/client-auth.sgml
doc/src/sgml/ddl.sgml
doc/src/sgml/func.sgml
doc/src/sgml/ref/grant.sgml
doc/src/sgml/ref/revoke.sgml
doc/src/sgml/user-manag.sgml
src/backend/catalog/aclchk.c
src/backend/utils/adt/acl.c
src/backend/utils/init/postinit.c
src/bin/pg_dump/dumputils.c
src/bin/psql/tab-complete.c
src/include/utils/acl.h

index 2185eebeb05cd8e21223cc528cb3707f9e59192e..22fe521bfb05c7874a5f2c61c7ca4eb96c3a40a8 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.88 2006/04/30 02:09:06 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.89 2006/04/30 21:15:32 tgl Exp $ -->
 
 <chapter id="client-authentication">
  <title>Client Authentication</title>
@@ -206,8 +206,6 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
        Multiple user names can be supplied by separating them with commas.
        A separate file containing user names can be specified by preceding the
        file name with <literal>@</>.
-       User and group connectivity can also be restricted by <command>GRANT
-       CONNECTION ON DATABASE</>.
       </para>
      </listitem>
     </varlistentry>
@@ -436,6 +434,17 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
    re-read the file.
   </para>
 
+  <tip>
+   <para>
+    To connect to a particular database, a user must not only pass the
+    <filename>pg_hba.conf</filename> checks, but must have the
+    <literal>CONNECT</> privilege for the database.  If you wish to
+    restrict which users can connect to which databases, it's usually
+    easier to control this by granting/revoking <literal>CONNECT</> privilege
+    than to put the rules into <filename>pg_hba.conf</filename> entries.
+   </para>
+  </tip>
+
   <para>
    Some examples of <filename>pg_hba.conf</filename> entries are shown in
    <xref linkend="example-pg-hba.conf">. See the next section for details on the
index 77bc1dd4970d2e5621de205a8964cda4c557a42b..a6fb4b3691f90c005ba1057939e18bdeeec361eb 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.56 2006/04/23 03:39:50 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.57 2006/04/30 21:15:32 tgl Exp $ -->
 
 <chapter id="ddl">
  <title>Data Definition</title>
@@ -1343,8 +1343,9 @@ ALTER TABLE products RENAME TO items;
    There are several different privileges: <literal>SELECT</>,
    <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
    <literal>RULE</>, <literal>REFERENCES</>, <literal>TRIGGER</>,
-   <literal>CREATE</>, <literal>TEMPORARY</>, <literal>EXECUTE</>, and
-   <literal>USAGE</>.  The privileges applicable to a particular
+   <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
+   <literal>EXECUTE</>, and <literal>USAGE</>.
+   The privileges applicable to a particular
    object vary depending on the object's type (table, function, etc).
    For complete information on the different types of privileges
    supported by <productname>PostgreSQL</productname>, refer to the
index b53bdca6fc397b4e0d786d0952da8a114212e3f4..1c6738b8cb4b3a22e3cb805213509ed8c1c50c93 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.315 2006/04/25 00:25:15 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.316 2006/04/30 21:15:32 tgl Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -9227,6 +9227,7 @@ SELECT has_table_privilege('myschema.mytable', 'select');
     arguments are analogous to <function>has_table_privilege</function>.
     The desired access privilege type must evaluate to
     <literal>CREATE</literal>,
+    <literal>CONNECT</literal>,
     <literal>TEMPORARY</literal>, or
     <literal>TEMP</literal> (which is equivalent to
     <literal>TEMPORARY</literal>).
index 03060f97212957c50a4d03e477768145a446385e..c6073dc35e451d7714f47835cf758edb760c9a5f 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.53 2006/04/30 02:09:06 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.54 2006/04/30 21:15:33 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -30,7 +30,7 @@ GRANT { { USAGE | SELECT | UPDATE }
     ON SEQUENCE <replaceable class="PARAMETER">sequencename</replaceable> [, ...]
     TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
 
-GRANT { { CREATE | TEMPORARY | TEMP | CONNECTION } [,...] | ALL [ PRIVILEGES ] }
+GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
     ON DATABASE <replaceable>dbname</replaceable> [, ...]
     TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
 
@@ -118,7 +118,8 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...]
    Depending on the type of object, the initial default privileges may
    include granting some privileges to <literal>PUBLIC</literal>.
    The default is no public access for tables, schemas, and tablespaces;
-   <literal>TEMP</> table creation privilege for databases;
+   <literal>CONNECT</> privilege and <literal>TEMP</> table creation privilege
+   for databases;
    <literal>EXECUTE</> privilege for functions; and
    <literal>USAGE</> privilege for languages.
    The object owner may of course revoke these privileges.  (For maximum
@@ -230,13 +231,12 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...]
     </varlistentry>
 
     <varlistentry>
-     <term>CONNECTION</term>
+     <term>CONNECT</term>
      <listitem>
       <para>
-       Allows the ability to connect to the specified database.
-       By default, Grant permissions allow users to connect to any database,
-       though <filename>pg_hba.conf</> can add additional connection
-       restrictions.
+       Allows the user to connect to the specified database.  This
+       privilege is checked at connection startup (in addition to checking
+       any restrictions imposed by <filename>pg_hba.conf</>).
       </para>
      </listitem>
     </varlistentry>
@@ -429,7 +429,7 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...]
                   X -- EXECUTE
                   U -- USAGE
                   C -- CREATE
-                  c -- CONNECTION
+                  c -- CONNECT
                   T -- TEMPORARY
             arwdRxt -- ALL PRIVILEGES (for tables)
                   * -- grant option for preceding privilege
index 034b946111c7a693b7372d14e174ab29eebc10c0..bccb8010b5f803d5f01cec8652bf90d64962a46e 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.37 2006/04/30 02:09:06 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.38 2006/04/30 21:15:33 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -35,7 +35,7 @@ REVOKE [ GRANT OPTION FOR ]
     [ CASCADE | RESTRICT ]
 
 REVOKE [ GRANT OPTION FOR ]
-    { { CREATE | TEMPORARY | TEMP | CONNECTION } [,...] | ALL [ PRIVILEGES ] }
+    { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
     ON DATABASE <replaceable>dbname</replaceable> [, ...]
     FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
     [ CASCADE | RESTRICT ]
index d05a9d3b047896a0503f9003ee10be965f8bf2df..41e6020091993e3607a50586ac3b172a85fd0fa0 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/user-manag.sgml,v 1.34 2006/03/10 19:10:49 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/user-manag.sgml,v 1.35 2006/04/30 21:15:32 tgl Exp $ -->
 
 <chapter id="user-manag">
  <title>Database Roles and Privileges</title>
@@ -294,9 +294,9 @@ ALTER ROLE myname SET enable_indexscan TO off;
    There are several different kinds of privilege: <literal>SELECT</>,
    <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
    <literal>RULE</>, <literal>REFERENCES</>, <literal>TRIGGER</>,
-   <literal>CREATE</>, <literal>TEMPORARY</>, <literal>EXECUTE</>,
-   and <literal>USAGE</>. For more
-   information on the different types of privileges supported by
+   <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
+   <literal>EXECUTE</>, and <literal>USAGE</>.
+   For more information on the different types of privileges supported by
    <productname>PostgreSQL</productname>, see the
    <xref linkend="sql-grant" endterm="sql-grant-title"> reference page.
   </para>
index 3b9701db077bf038cfdcd4d43d79c2e8f360dc02..a74c28e5b3d1c3ea9b9f1680fb695cc171a25be9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.126 2006/04/30 02:09:07 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.127 2006/04/30 21:15:33 tgl Exp $
  *
  * NOTES
  *       See acl.h.
@@ -1368,7 +1368,7 @@ string_to_privilege(const char *privname)
                return ACL_CREATE_TEMP;
        if (strcmp(privname, "temp") == 0)
                return ACL_CREATE_TEMP;
-       if (strcmp(privname, "connection") == 0)
+       if (strcmp(privname, "connect") == 0)
                return ACL_CONNECT;
        ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
@@ -1404,7 +1404,7 @@ privilege_to_string(AclMode privilege)
                case ACL_CREATE_TEMP:
                        return "TEMP";
                case ACL_CONNECT:
-                       return "CONNECTION";
+                       return "CONNECT";
                default:
                        elog(ERROR, "unrecognized privilege: %d", (int) privilege);
        }
@@ -1661,10 +1661,6 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
        ScanKeyData entry[1];
        SysScanDesc scan;
        HeapTuple       tuple;
-       Datum           aclDatum;
-       bool            isNull;
-       Acl                *acl;
-       Oid                     ownerId;
 
        /* Superusers bypass all permission checking. */
        if (superuser_arg(roleid))
@@ -1688,10 +1684,33 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
                                (errcode(ERRCODE_UNDEFINED_DATABASE),
                                 errmsg("database with OID %u does not exist", db_oid)));
 
-       ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
+       result = pg_database_tuple_aclmask(tuple, RelationGetDescr(pg_database),
+                                                                          roleid, mask, how);
+
+       systable_endscan(scan);
+       heap_close(pg_database, AccessShareLock);
+
+       return result;
+}
+
+/*
+ * This is split out so that ReverifyMyDatabase can perform an ACL check
+ * without a whole extra search of pg_database
+ */
+AclMode
+pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc,
+                                                 Oid roleid, AclMode mask, AclMaskHow how)
+{
+       AclMode         result;
+       Datum           aclDatum;
+       bool            isNull;
+       Acl                *acl;
+       Oid                     ownerId;
+
+       ownerId = ((Form_pg_database) GETSTRUCT(db_tuple))->datdba;
 
-       aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
-                                                       RelationGetDescr(pg_database), &isNull);
+       aclDatum = heap_getattr(db_tuple, Anum_pg_database_datacl,
+                                                       tupdesc, &isNull);
 
        if (isNull)
        {
@@ -1711,9 +1730,6 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
        if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
                pfree(acl);
 
-       systable_endscan(scan);
-       heap_close(pg_database, AccessShareLock);
-
        return result;
 }
 
index 4f64104ad3de7f1cf600031d229933438c9c0a42..0fa61196ea7c7be9cacda971d411a709e292fa86 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.132 2006/04/30 02:09:07 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.133 2006/04/30 21:15:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -553,7 +553,8 @@ acldefault(GrantObjectType objtype, Oid ownerId)
                        owner_default = ACL_ALL_RIGHTS_SEQUENCE;
                        break;
                case ACL_OBJECT_DATABASE:
-                       world_default = ACL_CREATE_TEMP | ACL_CONNECT;  /* not NO_RIGHTS! */
+                       /* for backwards compatibility, grant some rights by default */
+                       world_default = ACL_CREATE_TEMP | ACL_CONNECT;
                        owner_default = ACL_ALL_RIGHTS_DATABASE;
                        break;
                case ACL_OBJECT_FUNCTION:
@@ -1341,6 +1342,8 @@ convert_priv_string(text *priv_type_text)
                return ACL_CREATE_TEMP;
        if (pg_strcasecmp(priv_type, "TEMPORARY") == 0)
                return ACL_CREATE_TEMP;
+       if (pg_strcasecmp(priv_type, "CONNECT") == 0)
+               return ACL_CONNECT;
 
        ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1778,6 +1781,11 @@ convert_database_priv_string(text *priv_type_text)
        if (pg_strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0)
                return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
 
+       if (pg_strcasecmp(priv_type, "CONNECT") == 0)
+               return ACL_CONNECT;
+       if (pg_strcasecmp(priv_type, "CONNECT WITH GRANT OPTION") == 0)
+               return ACL_GRANT_OPTION_FOR(ACL_CONNECT);
+
        ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("unrecognized privilege type: \"%s\"", priv_type)));
index 63135d2d1e305862030a43cfc13403c0f80b383c..e89df5bb3afa19a5ecbba40ce9d61408a29f52b9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.163 2006/04/30 02:09:07 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.164 2006/04/30 21:15:33 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -51,7 +51,7 @@
 
 
 static bool FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace);
-static void ReverifyMyDatabase(const char *name, const char *user_name);
+static void ReverifyMyDatabase(const char *name, bool am_superuser);
 static void InitCommunication(void);
 static void ShutdownPostgres(int code, Datum arg);
 static bool ThereIsAtLeastOneRole(void);
@@ -127,12 +127,11 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
  * of pg_database.
  *
  * To avoid having to read pg_database more times than necessary
- * during session startup, this place is also fitting to set up any
- * database-specific configuration variables.
+ * during session startup, this place is also fitting to check CONNECT
+ * privilege and set up any database-specific configuration variables.
  */
 static void
-ReverifyMyDatabase(const char *name, const char *user_name)
+ReverifyMyDatabase(const char *name, bool am_superuser)
 {
        Relation        pgdbrel;
        SysScanDesc pgdbscan;
@@ -195,6 +194,22 @@ ReverifyMyDatabase(const char *name, const char *user_name)
                         errmsg("database \"%s\" is not currently accepting connections",
                                        name)));
 
+               /*
+                * Check privilege to connect to the database.  To avoid making
+                * a whole extra search of pg_database here, we don't go through
+                * pg_database_aclcheck, but instead use a lower-level routine
+                * that we can pass the pg_database tuple to.
+                */
+               if (!am_superuser &&
+                       pg_database_tuple_aclmask(tup, RelationGetDescr(pgdbrel),
+                                                                         GetUserId(),
+                                                                         ACL_CONNECT, ACLMASK_ANY) == 0)
+                       ereport(FATAL,
+                                       (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                                        errmsg("permission denied for database %s",
+                                                       NameStr(dbform->datname)),
+                                        errdetail("User does not have CONNECT privilege.")));
+
                /*
                 * Check connection limit for this database.
                 *
@@ -206,29 +221,12 @@ ReverifyMyDatabase(const char *name, const char *user_name)
                 * just document that the connection limit is approximate.
                 */
                if (dbform->datconnlimit >= 0 &&
-                       !superuser() &&
+                       !am_superuser &&
                        CountDBBackends(MyDatabaseId) > dbform->datconnlimit)
                        ereport(FATAL,
                                        (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
                                         errmsg("too many connections for database \"%s\"",
                                                        name)));
-
-               /*
-                * Checking for privilege to connect to the database
-                * We want to bypass the test if we are running in bootstrap mode
-                */
-               if (!IsBootstrapProcessingMode())
-               {
-                               if(pg_database_aclcheck(MyDatabaseId,GetUserId()
-                                       ,ACL_CONNECT) != ACLCHECK_OK )
-                               {
-                                       ereport(FATAL,
-                                       (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-                                               errmsg("couldn't connect to database %s", NameStr(dbform->datname)),
-                                               errdetail("User %s doesn't have the CONNECTION privilege for database %s.",
-                                user_name, NameStr(dbform->datname))));                                
-                               }
-               }
        }
 
        /*
@@ -476,15 +474,20 @@ InitPostgres(const char *dbname, const char *username)
        RelationCacheInitializePhase2();
 
        /*
-        * Figure out our postgres user id.  In standalone mode and in the
-        * autovacuum process, we use a fixed id, otherwise we figure it out from
-        * the authenticated user name.
+        * Figure out our postgres user id, and see if we are a superuser.
+        *
+        * In standalone mode and in the autovacuum process, we use a fixed id,
+        * otherwise we figure it out from the authenticated user name.
         */
        if (bootstrap || autovacuum)
+       {
                InitializeSessionUserIdStandalone();
+               am_superuser = true;
+       }
        else if (!IsUnderPostmaster)
        {
                InitializeSessionUserIdStandalone();
+               am_superuser = true;
                if (!ThereIsAtLeastOneRole())
                        ereport(WARNING,
                                        (errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -496,8 +499,12 @@ InitPostgres(const char *dbname, const char *username)
        {
                /* normal multiuser case */
                InitializeSessionUserId(username);
+               am_superuser = superuser();
        }
 
+       /* set up ACL framework (so ReverifyMyDatabase can check permissions) */
+       initialize_acl();
+
        /*
         * Unless we are bootstrapping, double-check that InitMyDatabaseInfo() got
         * a correct result.  We can't do this until all the database-access
@@ -505,7 +512,7 @@ InitPostgres(const char *dbname, const char *username)
         * superuser, so the above stuff has to happen first.)
         */
        if (!bootstrap)
-               ReverifyMyDatabase(dbname,username);
+               ReverifyMyDatabase(dbname, am_superuser);
 
        /*
         * Final phase of relation cache startup: write a new cache file if
@@ -514,14 +521,6 @@ InitPostgres(const char *dbname, const char *username)
         */
        RelationCacheInitializePhase3();
 
-       /*
-        * Check if user is a superuser.
-        */
-       if (bootstrap || autovacuum)
-               am_superuser = true;
-       else
-               am_superuser = superuser();
-
        /*
         * Check a normal user hasn't connected to a superuser reserved slot.
         */
@@ -540,9 +539,6 @@ InitPostgres(const char *dbname, const char *username)
        /* set default namespace search path */
        InitializeSearchPath();
 
-       /* set up ACL framework (currently just sets RolMemCache callback) */
-       initialize_acl();
-
        /* initialize client encoding */
        InitializeClientEncoding();
 
index 77e6d43fe020fc71b670891e41894deaf953bd43..86c930b8add3642c613b600b13b916c71312df91 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.26 2006/03/05 15:58:50 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.27 2006/04/30 21:15:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -605,6 +605,7 @@ do { \
        else if (strcmp(type, "DATABASE") == 0)
        {
                CONVERT_PRIV('C', "CREATE");
+               CONVERT_PRIV('c', "CONNECT");
                CONVERT_PRIV('T', "TEMPORARY");
        }
        else if (strcmp(type, "TABLESPACE") == 0)
index a90d7eb72cfb4f03f11cc2bd69e8215ea7db0ba6..ad8f0f841b238741afc768534818403e3f2a36d8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2006, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.150 2006/04/02 09:02:41 alvherre Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.151 2006/04/30 21:15:33 tgl Exp $
  */
 
 /*----------------------------------------------------------------------
@@ -1373,7 +1373,8 @@ psql_completion(char *text, int start, int end)
        {
                static const char *const list_privileg[] =
                {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES",
-               "TRIGGER", "CREATE", "TEMPORARY", "EXECUTE", "USAGE", "ALL", NULL};
+                "TRIGGER", "CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE",
+                "ALL", NULL};
 
                COMPLETE_WITH_LIST(list_privileg);
        }
index c329b6aab81d16a2d9ece7352d5d016c5306e475..7651fba290c1148c5e046ef5816bdcdddc6a6936 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.94 2006/04/30 02:09:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.95 2006/04/30 21:15:33 tgl Exp $
  *
  * NOTES
  *       An ACL array is simply an array of AclItems, representing the union
@@ -24,6 +24,8 @@
 #ifndef ACL_H
 #define ACL_H
 
+#include "access/htup.h"
+#include "access/tupdesc.h"
 #include "nodes/parsenodes.h"
 #include "utils/array.h"
 
@@ -145,7 +147,7 @@ typedef ArrayType Acl;
  */
 #define ACL_ALL_RIGHTS_RELATION                (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_RULE|ACL_REFERENCES|ACL_TRIGGER)
 #define ACL_ALL_RIGHTS_SEQUENCE                (ACL_USAGE|ACL_SELECT|ACL_UPDATE)
-#define ACL_ALL_RIGHTS_DATABASE                (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT )
+#define ACL_ALL_RIGHTS_DATABASE                (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
 #define ACL_ALL_RIGHTS_FUNCTION                (ACL_EXECUTE)
 #define ACL_ALL_RIGHTS_LANGUAGE                (ACL_USAGE)
 #define ACL_ALL_RIGHTS_NAMESPACE       (ACL_USAGE|ACL_CREATE)
@@ -250,6 +252,8 @@ extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
                                 AclMode mask, AclMaskHow how);
 extern AclMode pg_database_aclmask(Oid db_oid, Oid roleid,
                                        AclMode mask, AclMaskHow how);
+extern AclMode pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc,
+                                       Oid roleid, AclMode mask, AclMaskHow how);
 extern AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid,
                                AclMode mask, AclMaskHow how);
 extern AclMode pg_language_aclmask(Oid lang_oid, Oid roleid,