Updated patch attached, based on comments from Ryan Bradetich and Tom
Lane, and sync'd to latest CVS version.

...Robert

On Mon, Sep 1, 2008 at 9:33 PM, Tom Lane <[EMAIL PROTECTED]> wrote:
> "Ryan Bradetich" <[EMAIL PROTECTED]> writes:
>> On Mon, Sep 1, 2008 at 1:00 PM, Tom Lane <[EMAIL PROTECTED]> wrote:
>>> [ something about "your patch" ]
>
>> This is Robert Haas's patch for the September 2008 commit-fest.
>> I am just offering my review.
>
> Sorry about that, I got confused by the reply-to-a-reply.
>
>> Does my first suggestion still make sense for removing the TRUNCATE in
>> pg_class_aclmask() when pg_Authid.rolcatupdate is not set?
>
> Probably.  AFAICS it should be treated exactly like ACL_DELETE, so
> anyplace that acl-whacking code is doing something for ACL_DELETE and
> the patch doesn't add in ACL_TRUNCATE, I'd be suspicious ...
>
>                        regards, tom lane
>
> --
> Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-hackers
>
Index: doc/src/sgml/ddl.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ddl.sgml,v
retrieving revision 1.82
diff -c -r1.82 ddl.sgml
*** doc/src/sgml/ddl.sgml	9 May 2008 23:32:03 -0000	1.82
--- doc/src/sgml/ddl.sgml	6 Sep 2008 03:07:12 -0000
***************
*** 1356,1362 ****
    <para>
     There are several different privileges: <literal>SELECT</>,
     <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
!    <literal>REFERENCES</>, <literal>TRIGGER</>,
     <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
     <literal>EXECUTE</>, and <literal>USAGE</>.
     The privileges applicable to a particular
--- 1356,1362 ----
    <para>
     There are several different privileges: <literal>SELECT</>,
     <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
!    <literal>TRUNCATE</>, <literal>REFERENCES</>, <literal>TRIGGER</>,
     <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
     <literal>EXECUTE</>, and <literal>USAGE</>.
     The privileges applicable to a particular
Index: doc/src/sgml/user-manag.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v
retrieving revision 1.39
diff -c -r1.39 user-manag.sgml
*** doc/src/sgml/user-manag.sgml	1 Feb 2007 00:28:18 -0000	1.39
--- doc/src/sgml/user-manag.sgml	6 Sep 2008 03:07:13 -0000
***************
*** 293,299 ****
     granted.
     There are several different kinds of privilege: <literal>SELECT</>,
     <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
!    <literal>REFERENCES</>, <literal>TRIGGER</>,
     <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
     <literal>EXECUTE</>, and <literal>USAGE</>.
     For more information on the different types of privileges supported by
--- 293,299 ----
     granted.
     There are several different kinds of privilege: <literal>SELECT</>,
     <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
!    <literal>TRUNCATE</>, <literal>REFERENCES</>, <literal>TRIGGER</>,
     <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
     <literal>EXECUTE</>, and <literal>USAGE</>.
     For more information on the different types of privileges supported by
Index: doc/src/sgml/ref/grant.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v
retrieving revision 1.70
diff -c -r1.70 grant.sgml
*** doc/src/sgml/ref/grant.sgml	3 Jul 2008 15:59:55 -0000	1.70
--- doc/src/sgml/ref/grant.sgml	6 Sep 2008 03:07:14 -0000
***************
*** 20,26 ****
  
   <refsynopsisdiv>
  <synopsis>
! GRANT { { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRIGGER }
      [,...] | ALL [ PRIVILEGES ] }
      ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
      TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
--- 20,26 ----
  
   <refsynopsisdiv>
  <synopsis>
! GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
      [,...] | ALL [ PRIVILEGES ] }
      ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
      TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
***************
*** 193,198 ****
--- 193,208 ----
      </varlistentry>
  
      <varlistentry>
+      <term>TRUNCATE</term>
+      <listitem>
+       <para>
+        Allows <xref linkend="sql-truncate" endterm="sql-truncate-title"> on
+        the specified table.
+       </para>
+      </listitem>
+     </varlistentry>
+ 
+     <varlistentry>
       <term>REFERENCES</term>
       <listitem>
        <para>
***************
*** 421,428 ****
  =&gt; \z mytable
                  Access privileges
   Schema |  Name   | Type  |  Access privileges   
! --------+---------+-------+----------------------
!  public | mytable | table | miriam=arwdxt/miriam
                            : =r/miriam
                            : admin=arw/miriam
  (1 row)
--- 431,438 ----
  =&gt; \z mytable
                  Access privileges
   Schema |  Name   | Type  |  Access privileges   
! --------+---------+-------+-----------------------
!  public | mytable | table | miriam=arwdDxt/miriam
                            : =r/miriam
                            : admin=arw/miriam
  (1 row)
***************
*** 436,441 ****
--- 446,452 ----
                    w -- UPDATE ("write")
                    a -- INSERT ("append")
                    d -- DELETE
+                   D -- TRUNCATE
                    x -- REFERENCES
                    t -- TRIGGER
                    X -- EXECUTE
***************
*** 443,449 ****
                    C -- CREATE
                    c -- CONNECT
                    T -- TEMPORARY
!              arwdxt -- ALL PRIVILEGES (for tables)
                    * -- grant option for preceding privilege
  
                /yyyy -- role that granted this privilege
--- 454,460 ----
                    C -- CREATE
                    c -- CONNECT
                    T -- TEMPORARY
!             arwdDxt -- ALL PRIVILEGES (for tables)
                    * -- grant option for preceding privilege
  
                /yyyy -- role that granted this privilege
***************
*** 466,472 ****
      object type, as explained above.  The first <command>GRANT</> or
      <command>REVOKE</> on an object
      will instantiate the default privileges (producing, for example,
!     <literal>{miriam=arwdxt/miriam}</>) and then modify them per the
      specified request.
     </para>
  
--- 477,483 ----
      object type, as explained above.  The first <command>GRANT</> or
      <command>REVOKE</> on an object
      will instantiate the default privileges (producing, for example,
!     <literal>{miriam=arwdDxt/miriam}</>) and then modify them per the
      specified request.
     </para>
  
Index: doc/src/sgml/ref/revoke.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v
retrieving revision 1.47
diff -c -r1.47 revoke.sgml
*** doc/src/sgml/ref/revoke.sgml	3 Mar 2008 19:17:27 -0000	1.47
--- doc/src/sgml/ref/revoke.sgml	6 Sep 2008 03:07:14 -0000
***************
*** 21,27 ****
   <refsynopsisdiv>
  <synopsis>
  REVOKE [ GRANT OPTION FOR ]
!     { { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRIGGER }
      [,...] | ALL [ PRIVILEGES ] }
      ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
      FROM { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...]
--- 21,27 ----
   <refsynopsisdiv>
  <synopsis>
  REVOKE [ GRANT OPTION FOR ]
!     { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
      [,...] | ALL [ PRIVILEGES ] }
      ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
      FROM { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...]
Index: doc/src/sgml/ref/truncate.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/truncate.sgml,v
retrieving revision 1.27
diff -c -r1.27 truncate.sgml
*** doc/src/sgml/ref/truncate.sgml	17 May 2008 23:36:27 -0000	1.27
--- doc/src/sgml/ref/truncate.sgml	6 Sep 2008 03:07:14 -0000
***************
*** 97,103 ****
    <title>Notes</title>
  
    <para>
!    Only the owner of a table can <command>TRUNCATE</> it.
    </para>
  
    <para>
--- 97,104 ----
    <title>Notes</title>
  
    <para>
!    You must have the <literal>TRUNCATE</literal> privilege on the table
!    to truncate it.
    </para>
  
    <para>
Index: src/backend/catalog/aclchk.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/aclchk.c,v
retrieving revision 1.147
diff -c -r1.147 aclchk.c
*** src/backend/catalog/aclchk.c	19 Jun 2008 00:46:03 -0000	1.147
--- src/backend/catalog/aclchk.c	6 Sep 2008 03:07:16 -0000
***************
*** 1331,1336 ****
--- 1331,1338 ----
  		return ACL_UPDATE;
  	if (strcmp(privname, "delete") == 0)
  		return ACL_DELETE;
+ 	if (strcmp(privname, "truncate") == 0)
+ 		return ACL_TRUNCATE;
  	if (strcmp(privname, "references") == 0)
  		return ACL_REFERENCES;
  	if (strcmp(privname, "trigger") == 0)
***************
*** 1368,1373 ****
--- 1370,1377 ----
  			return "UPDATE";
  		case ACL_DELETE:
  			return "DELETE";
+ 		case ACL_TRUNCATE:
+ 			return "TRUNCATE";
  		case ACL_REFERENCES:
  			return "REFERENCES";
  		case ACL_TRIGGER:
***************
*** 1582,1588 ****
  	 * protected in this way.  Assume the view rules can take care of
  	 * themselves.	ACL_USAGE is if we ever have system sequences.
  	 */
! 	if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE)) &&
  		IsSystemClass(classForm) &&
  		classForm->relkind != RELKIND_VIEW &&
  		!has_rolcatupdate(roleid) &&
--- 1586,1593 ----
  	 * protected in this way.  Assume the view rules can take care of
  	 * themselves.	ACL_USAGE is if we ever have system sequences.
  	 */
! 	if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE
! 		| ACL_TRUNCATE)) &&
  		IsSystemClass(classForm) &&
  		classForm->relkind != RELKIND_VIEW &&
  		!has_rolcatupdate(roleid) &&
***************
*** 1591,1597 ****
  #ifdef ACLDEBUG
  		elog(DEBUG2, "permission denied for system catalog update");
  #endif
! 		mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE);
  	}
  
  	/*
--- 1596,1603 ----
  #ifdef ACLDEBUG
  		elog(DEBUG2, "permission denied for system catalog update");
  #endif
! 		mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE |
! 			ACL_TRUNCATE);
  	}
  
  	/*
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.265
diff -c -r1.265 tablecmds.c
*** src/backend/commands/tablecmds.c	1 Sep 2008 20:42:44 -0000	1.265
--- src/backend/commands/tablecmds.c	6 Sep 2008 03:07:21 -0000
***************
*** 989,994 ****
--- 989,996 ----
  static void
  truncate_check_rel(Relation rel)
  {
+ 	AclResult	aclresult;
+ 
  	/* Only allow truncate on regular tables */
  	if (rel->rd_rel->relkind != RELKIND_RELATION)
  		ereport(ERROR,
***************
*** 997,1004 ****
  						RelationGetRelationName(rel))));
  
  	/* Permissions checks */
! 	if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
! 		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
  					   RelationGetRelationName(rel));
  
  	if (!allowSystemTableMods && IsSystemRelation(rel))
--- 999,1008 ----
  						RelationGetRelationName(rel))));
  
  	/* Permissions checks */
! 	aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
! 								  ACL_TRUNCATE);
! 	if (aclresult != ACLCHECK_OK)
! 		aclcheck_error(aclresult, ACL_KIND_CLASS,
  					   RelationGetRelationName(rel));
  
  	if (!allowSystemTableMods && IsSystemRelation(rel))
Index: src/backend/utils/adt/acl.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/acl.c,v
retrieving revision 1.140
diff -c -r1.140 acl.c
*** src/backend/utils/adt/acl.c	25 Mar 2008 22:42:43 -0000	1.140
--- src/backend/utils/adt/acl.c	6 Sep 2008 03:07:23 -0000
***************
*** 265,270 ****
--- 265,273 ----
  			case ACL_DELETE_CHR:
  				read = ACL_DELETE;
  				break;
+ 			case ACL_TRUNCATE_CHR:
+ 				read = ACL_TRUNCATE;
+ 				break;
  			case ACL_REFERENCES_CHR:
  				read = ACL_REFERENCES;
  				break;
***************
*** 1323,1328 ****
--- 1326,1333 ----
  		return ACL_UPDATE;
  	if (pg_strcasecmp(priv_type, "DELETE") == 0)
  		return ACL_DELETE;
+ 	if (pg_strcasecmp(priv_type, "TRUNCATE") == 0)
+ 		return ACL_TRUNCATE;
  	if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
  		return ACL_REFERENCES;
  	if (pg_strcasecmp(priv_type, "TRIGGER") == 0)
***************
*** 1548,1553 ****
--- 1553,1563 ----
  	if (pg_strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0)
  		return ACL_GRANT_OPTION_FOR(ACL_DELETE);
  
+ 	if (pg_strcasecmp(priv_type, "TRUNCATE") == 0)
+ 		return ACL_TRUNCATE;
+ 	if (pg_strcasecmp(priv_type, "TRUNCATE WITH GRANT OPTION") == 0)
+ 		return ACL_GRANT_OPTION_FOR(ACL_TRUNCATE);
+ 
  	if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
  		return ACL_REFERENCES;
  	if (pg_strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0)
Index: src/bin/pg_dump/dumputils.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v
retrieving revision 1.40
diff -c -r1.40 dumputils.c
*** src/bin/pg_dump/dumputils.c	1 Jan 2008 19:45:55 -0000	1.40
--- src/bin/pg_dump/dumputils.c	6 Sep 2008 03:07:24 -0000
***************
*** 656,661 ****
--- 656,663 ----
  			if (remoteVersion >= 70200)
  			{
  				CONVERT_PRIV('d', "DELETE");
+ 				if (remoteVersion >= 80400)
+ 					CONVERT_PRIV('D', "TRUNCATE");
  				CONVERT_PRIV('x', "REFERENCES");
  				CONVERT_PRIV('t', "TRIGGER");
  			}
Index: src/bin/psql/tab-complete.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v
retrieving revision 1.171
diff -c -r1.171 tab-complete.c
*** src/bin/psql/tab-complete.c	16 Aug 2008 01:36:35 -0000	1.171
--- src/bin/psql/tab-complete.c	6 Sep 2008 03:07:26 -0000
***************
*** 1610,1617 ****
  			 pg_strcasecmp(prev_wd, "REVOKE") == 0)
  	{
  		static const char *const list_privileg[] =
! 		{"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES",
! 			"TRIGGER", "CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE",
  		"ALL", NULL};
  
  		COMPLETE_WITH_LIST(list_privileg);
--- 1610,1618 ----
  			 pg_strcasecmp(prev_wd, "REVOKE") == 0)
  	{
  		static const char *const list_privileg[] =
! 		{"SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "RULE",
! 			"REFERENCES", "TRIGGER", "CREATE", "CONNECT", "TEMPORARY",
! 			"EXECUTE", "USAGE",
  		"ALL", NULL};
  
  		COMPLETE_WITH_LIST(list_privileg);
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.374
diff -c -r1.374 parsenodes.h
*** src/include/nodes/parsenodes.h	1 Sep 2008 20:42:45 -0000	1.374
--- src/include/nodes/parsenodes.h	6 Sep 2008 03:07:28 -0000
***************
*** 63,69 ****
  #define ACL_SELECT		(1<<1)
  #define ACL_UPDATE		(1<<2)
  #define ACL_DELETE		(1<<3)
! /* #define ACL_RULE		(1<<4)	unused, available */
  #define ACL_REFERENCES	(1<<5)
  #define ACL_TRIGGER		(1<<6)
  #define ACL_EXECUTE		(1<<7)	/* for functions */
--- 63,69 ----
  #define ACL_SELECT		(1<<1)
  #define ACL_UPDATE		(1<<2)
  #define ACL_DELETE		(1<<3)
! #define ACL_TRUNCATE	(1<<4)
  #define ACL_REFERENCES	(1<<5)
  #define ACL_TRIGGER		(1<<6)
  #define ACL_EXECUTE		(1<<7)	/* for functions */
Index: src/include/utils/acl.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/acl.h,v
retrieving revision 1.103
diff -c -r1.103 acl.h
*** src/include/utils/acl.h	1 Jan 2008 19:45:59 -0000	1.103
--- src/include/utils/acl.h	6 Sep 2008 03:07:28 -0000
***************
*** 128,133 ****
--- 128,134 ----
  #define ACL_SELECT_CHR			'r'		/* formerly known as "read" */
  #define ACL_UPDATE_CHR			'w'		/* formerly known as "write" */
  #define ACL_DELETE_CHR			'd'
+ #define ACL_TRUNCATE_CHR		'D'		/* super-delete, as it were */
  #define ACL_REFERENCES_CHR		'x'
  #define ACL_TRIGGER_CHR			't'
  #define ACL_EXECUTE_CHR			'X'
***************
*** 137,148 ****
  #define ACL_CONNECT_CHR			'c'
  
  /* string holding all privilege code chars, in order by bitmask position */
! #define ACL_ALL_RIGHTS_STR	"arwdRxtXUCTc"
  
  /*
   * Bitmasks defining "all rights" for each supported object type
   */
! #define ACL_ALL_RIGHTS_RELATION		(ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|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_FUNCTION		(ACL_EXECUTE)
--- 138,149 ----
  #define ACL_CONNECT_CHR			'c'
  
  /* string holding all privilege code chars, in order by bitmask position */
! #define ACL_ALL_RIGHTS_STR	"arwdDxtXUCTc"
  
  /*
   * Bitmasks defining "all rights" for each supported object type
   */
! #define ACL_ALL_RIGHTS_RELATION		(ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|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_FUNCTION		(ACL_EXECUTE)
Index: src/test/regress/expected/dependency.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/dependency.out,v
retrieving revision 1.7
diff -c -r1.7 dependency.out
*** src/test/regress/expected/dependency.out	3 Jul 2008 15:59:55 -0000	1.7
--- src/test/regress/expected/dependency.out	6 Sep 2008 03:07:30 -0000
***************
*** 21,27 ****
  REVOKE SELECT ON deptest FROM GROUP regression_group;
  DROP GROUP regression_group;
  -- can't drop the user if we revoke the privileges partially
! REVOKE SELECT, INSERT, UPDATE, DELETE, RULE, REFERENCES ON deptest FROM regression_user;
  DROP USER regression_user;
  ERROR:  role "regression_user" cannot be dropped because some objects depend on it
  DETAIL:  access to table deptest
--- 21,27 ----
  REVOKE SELECT ON deptest FROM GROUP regression_group;
  DROP GROUP regression_group;
  -- can't drop the user if we revoke the privileges partially
! REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES ON deptest FROM regression_user;
  DROP USER regression_user;
  ERROR:  role "regression_user" cannot be dropped because some objects depend on it
  DETAIL:  access to table deptest
***************
*** 70,79 ****
  \z deptest1
                               Access privileges
   Schema |   Name   | Type  |               Access privileges                
! --------+----------+-------+------------------------------------------------
!  public | deptest1 | table | regression_user0=arwdxt/regression_user0
!                            : regression_user1=a*r*w*d*x*t*/regression_user0
!                            : regression_user2=arwdxt/regression_user1
  (1 row)
  
  DROP OWNED BY regression_user1;
--- 70,79 ----
  \z deptest1
                               Access privileges
   Schema |   Name   | Type  |               Access privileges                
! --------+----------+-------+--------------------------------------------------
!  public | deptest1 | table | regression_user0=arwdDxt/regression_user0
!                            : regression_user1=a*r*w*d*D*x*t*/regression_user0
!                            : regression_user2=arwdDxt/regression_user1
  (1 row)
  
  DROP OWNED BY regression_user1;
***************
*** 81,88 ****
  \z deptest1
                            Access privileges
   Schema |   Name   | Type  |            Access privileges             
! --------+----------+-------+------------------------------------------
!  public | deptest1 | table | regression_user0=arwdxt/regression_user0
  (1 row)
  
  -- table was dropped
--- 81,88 ----
  \z deptest1
                            Access privileges
   Schema |   Name   | Type  |            Access privileges             
! --------+----------+-------+-------------------------------------------
!  public | deptest1 | table | regression_user0=arwdDxt/regression_user0
  (1 row)
  
  -- table was dropped
Index: src/test/regress/expected/privileges.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/privileges.out,v
retrieving revision 1.38
diff -c -r1.38 privileges.out
*** src/test/regress/expected/privileges.out	3 Jul 2008 16:01:10 -0000	1.38
--- src/test/regress/expected/privileges.out	6 Sep 2008 03:07:30 -0000
***************
*** 16,23 ****
  CREATE USER regressuser2;
  CREATE USER regressuser3;
  CREATE USER regressuser4;
! CREATE USER regressuser4;	-- duplicate
! ERROR:  role "regressuser4" already exists
  CREATE GROUP regressgroup1;
  CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2;
  ALTER GROUP regressgroup1 ADD USER regressuser4;
--- 16,24 ----
  CREATE USER regressuser2;
  CREATE USER regressuser3;
  CREATE USER regressuser4;
! CREATE USER regressuser5;
! CREATE USER regressuser5;	-- duplicate
! ERROR:  role "regressuser5" already exists
  CREATE GROUP regressgroup1;
  CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2;
  ALTER GROUP regressgroup1 ADD USER regressuser4;
***************
*** 42,47 ****
--- 43,49 ----
  INSERT INTO atest1 VALUES (1, 'one');
  DELETE FROM atest1;
  UPDATE atest1 SET a = 1 WHERE b = 'blech';
+ TRUNCATE atest1;
  LOCK atest1 IN ACCESS EXCLUSIVE MODE;
  REVOKE ALL ON atest1 FROM PUBLIC;
  SELECT * FROM atest1;
***************
*** 60,65 ****
--- 62,68 ----
  GRANT SELECT ON atest2 TO regressuser2;
  GRANT UPDATE ON atest2 TO regressuser3;
  GRANT INSERT ON atest2 TO regressuser4;
+ GRANT TRUNCATE ON atest2 TO regressuser5;
  SET SESSION AUTHORIZATION regressuser2;
  SELECT session_user, current_user;
   session_user | current_user 
***************
*** 96,101 ****
--- 99,106 ----
  ERROR:  permission denied for relation atest2
  DELETE FROM atest2; -- fail
  ERROR:  permission denied for relation atest2
+ TRUNCATE atest2; -- fail
+ ERROR:  permission denied for relation atest2
  LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail
  ERROR:  permission denied for relation atest2
  COPY atest2 FROM stdin; -- fail
***************
*** 147,152 ****
--- 152,159 ----
  ERROR:  permission denied for relation atest2
  DELETE FROM atest2; -- fail
  ERROR:  permission denied for relation atest2
+ TRUNCATE atest2; -- fail
+ ERROR:  permission denied for relation atest2
  LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok
  COPY atest2 FROM stdin; -- fail
  ERROR:  permission denied for relation atest2
***************
*** 285,290 ****
--- 292,302 ----
  DROP FUNCTION testfunc1(int); -- ok
  -- restore to sanity
  GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC;
+ -- truncate
+ SET SESSION AUTHORIZATION regressuser5;
+ TRUNCATE atest2; -- ok
+ TRUNCATE atest3; -- fail
+ ERROR:  permission denied for relation atest3
  -- has_table_privilege function
  -- bad-input checks
  select has_table_privilege(NULL,'pg_authid','select');
***************
*** 375,380 ****
--- 387,398 ----
   t
  (1 row)
  
+ select has_table_privilege('pg_authid','truncate');
+  has_table_privilege 
+ ---------------------
+  t
+ (1 row)
+ 
  select has_table_privilege(t1.oid,'select')
  from (select oid from pg_class where relname = 'pg_authid') as t1;
   has_table_privilege 
***************
*** 452,457 ****
--- 470,481 ----
   f
  (1 row)
  
+ select has_table_privilege('pg_class','truncate');
+  has_table_privilege 
+ ---------------------
+  f
+ (1 row)
+ 
  select has_table_privilege(t1.oid,'select')
  from (select oid from pg_class where relname = 'pg_class') as t1;
   has_table_privilege 
***************
*** 527,532 ****
--- 551,562 ----
   f
  (1 row)
  
+ select has_table_privilege('atest1','truncate');
+  has_table_privilege 
+ ---------------------
+  f
+ (1 row)
+ 
  select has_table_privilege(t1.oid,'select')
  from (select oid from pg_class where relname = 'atest1') as t1;
   has_table_privilege 
Index: src/test/regress/sql/dependency.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/dependency.sql,v
retrieving revision 1.4
diff -c -r1.4 dependency.sql
*** src/test/regress/sql/dependency.sql	21 Aug 2006 00:57:26 -0000	1.4
--- src/test/regress/sql/dependency.sql	6 Sep 2008 03:07:30 -0000
***************
*** 21,27 ****
  DROP GROUP regression_group;
  
  -- can't drop the user if we revoke the privileges partially
! REVOKE SELECT, INSERT, UPDATE, DELETE, RULE, REFERENCES ON deptest FROM regression_user;
  DROP USER regression_user;
  
  -- now we are OK to drop him
--- 21,27 ----
  DROP GROUP regression_group;
  
  -- can't drop the user if we revoke the privileges partially
! REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES ON deptest FROM regression_user;
  DROP USER regression_user;
  
  -- now we are OK to drop him
Index: src/test/regress/sql/privileges.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/privileges.sql,v
retrieving revision 1.20
diff -c -r1.20 privileges.sql
*** src/test/regress/sql/privileges.sql	3 Jul 2008 16:01:10 -0000	1.20
--- src/test/regress/sql/privileges.sql	6 Sep 2008 03:07:30 -0000
***************
*** 23,29 ****
  CREATE USER regressuser2;
  CREATE USER regressuser3;
  CREATE USER regressuser4;
! CREATE USER regressuser4;	-- duplicate
  
  CREATE GROUP regressgroup1;
  CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2;
--- 23,30 ----
  CREATE USER regressuser2;
  CREATE USER regressuser3;
  CREATE USER regressuser4;
! CREATE USER regressuser5;
! CREATE USER regressuser5;	-- duplicate
  
  CREATE GROUP regressgroup1;
  CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2;
***************
*** 45,50 ****
--- 46,52 ----
  INSERT INTO atest1 VALUES (1, 'one');
  DELETE FROM atest1;
  UPDATE atest1 SET a = 1 WHERE b = 'blech';
+ TRUNCATE atest1;
  LOCK atest1 IN ACCESS EXCLUSIVE MODE;
  
  REVOKE ALL ON atest1 FROM PUBLIC;
***************
*** 58,63 ****
--- 60,66 ----
  GRANT SELECT ON atest2 TO regressuser2;
  GRANT UPDATE ON atest2 TO regressuser3;
  GRANT INSERT ON atest2 TO regressuser4;
+ GRANT TRUNCATE ON atest2 TO regressuser5;
  
  
  SET SESSION AUTHORIZATION regressuser2;
***************
*** 75,80 ****
--- 78,84 ----
  SELECT * FROM atest1 FOR UPDATE; -- ok
  SELECT * FROM atest2 FOR UPDATE; -- fail
  DELETE FROM atest2; -- fail
+ TRUNCATE atest2; -- fail
  LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail
  COPY atest2 FROM stdin; -- fail
  GRANT ALL ON atest1 TO PUBLIC; -- fail
***************
*** 99,104 ****
--- 103,109 ----
  SELECT * FROM atest1 FOR UPDATE; -- fail
  SELECT * FROM atest2 FOR UPDATE; -- fail
  DELETE FROM atest2; -- fail
+ TRUNCATE atest2; -- fail
  LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok
  COPY atest2 FROM stdin; -- fail
  
***************
*** 205,210 ****
--- 210,219 ----
  -- restore to sanity
  GRANT ALL PRIVILEGES ON LANGUAGE sql TO PUBLIC;
  
+ -- truncate
+ SET SESSION AUTHORIZATION regressuser5;
+ TRUNCATE atest2; -- ok
+ TRUNCATE atest3; -- fail
  
  -- has_table_privilege function
  
***************
*** 243,248 ****
--- 252,258 ----
  
  select has_table_privilege('pg_authid','update');
  select has_table_privilege('pg_authid','delete');
+ select has_table_privilege('pg_authid','truncate');
  
  select has_table_privilege(t1.oid,'select')
  from (select oid from pg_class where relname = 'pg_authid') as t1;
***************
*** 272,277 ****
--- 282,288 ----
  
  select has_table_privilege('pg_class','update');
  select has_table_privilege('pg_class','delete');
+ select has_table_privilege('pg_class','truncate');
  
  select has_table_privilege(t1.oid,'select')
  from (select oid from pg_class where relname = 'pg_class') as t1;
***************
*** 298,303 ****
--- 309,315 ----
  
  select has_table_privilege('atest1','update');
  select has_table_privilege('atest1','delete');
+ select has_table_privilege('atest1','truncate');
  
  select has_table_privilege(t1.oid,'select')
  from (select oid from pg_class where relname = 'atest1') as t1;
-- 
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