Index: doc/src/sgml/func.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v retrieving revision 1.301 diff -c -r1.301 func.sgml *** doc/src/sgml/func.sgml 28 Dec 2005 01:29:58 -0000 1.301 --- doc/src/sgml/func.sgml 4 Jan 2006 03:38:01 -0000 *************** *** 8961,8968 **** The desired access privilege type is specified by a text string, which must evaluate to one of the values SELECT, INSERT, UPDATE, ! DELETE, RULE, REFERENCES, or ! TRIGGER. (Case of the string is not significant, however.) An example is: SELECT has_table_privilege('myschema.mytable', 'select'); --- 8961,8969 ---- The desired access privilege type is specified by a text string, which must evaluate to one of the values SELECT, INSERT, UPDATE, ! DELETE, RULE, REFERENCES, ! TRIGGER, TRUNCATE, VACUUM, or ! ANALYZE. (Case of the string is not significant, however.) An example is: SELECT has_table_privilege('myschema.mytable', 'select'); Index: doc/src/sgml/information_schema.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/information_schema.sgml,v retrieving revision 1.23 diff -c -r1.23 information_schema.sgml *** doc/src/sgml/information_schema.sgml 8 Dec 2005 20:48:10 -0000 1.23 --- doc/src/sgml/information_schema.sgml 4 Jan 2006 03:38:01 -0000 *************** *** 2395,2401 **** Type of the privilege: SELECT, DELETE, INSERT, UPDATE, REFERENCES, ! RULE, or TRIGGER --- 2395,2403 ---- Type of the privilege: SELECT, DELETE, INSERT, UPDATE, REFERENCES, ! RULE, TRIGGER, ! TRUNCATE, VACUUM, or ! ANALYZE. *************** *** 3643,3649 **** Type of the privilege: SELECT, DELETE, INSERT, UPDATE, REFERENCES, ! RULE, or TRIGGER --- 3645,3653 ---- Type of the privilege: SELECT, DELETE, INSERT, UPDATE, REFERENCES, ! RULE, TRIGGER, ! TRUNCATE, VACUUM, or ! ANALYZE. Index: doc/src/sgml/user-manag.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v retrieving revision 1.33 diff -c -r1.33 user-manag.sgml *** doc/src/sgml/user-manag.sgml 20 Oct 2005 19:18:00 -0000 1.33 --- doc/src/sgml/user-manag.sgml 4 Jan 2006 03:38:01 -0000 *************** *** 296,301 **** --- 296,302 ---- There are several different kinds of privilege: SELECT, INSERT, UPDATE, DELETE, RULE, REFERENCES, TRIGGER, + TRUNCATE, VACUUM, ANALYZE, CREATE, TEMPORARY, EXECUTE, and 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.50 diff -c -r1.50 grant.sgml *** doc/src/sgml/ref/grant.sgml 20 Oct 2005 19:18:01 -0000 1.50 --- doc/src/sgml/ref/grant.sgml 4 Jan 2006 03:38:02 -0000 *************** *** 20,26 **** ! GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ PRIVILEGES ] } ON [ TABLE ] tablename [, ...] TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ] --- 20,26 ---- ! GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER | TRUNCATE | VACUUM | ANALYZE } [,...] | ALL [ PRIVILEGES ] } ON [ TABLE ] tablename [, ...] TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ] *************** *** 205,210 **** --- 205,243 ---- + TRUNCATE + + + Allows the truncation of the specified table. NOTE: This will NOT execute + triggers defined on the table. Additionally, this requires locking the table + exclusivly because it does not follow normal MVCC rules. See the statement. + + + + + + VACUUM + + + Allows the vacuuming of the specified table. Note: This implies ANALYZE + rights. See the + statement. + + + + + + ANALYZE + + + Allows the analyzing of the specified table. See the statement. + + + + + CREATE *************** *** 402,408 **** U -- USAGE C -- CREATE T -- TEMPORARY ! arwdRxt -- ALL PRIVILEGES (for tables) * -- grant option for preceding privilege /yyyy -- user who granted this privilege --- 435,444 ---- U -- USAGE C -- CREATE T -- TEMPORARY ! e -- TRUNCATE ! V -- VACUUM ! A -- ANALYZE ! arwdRxteVA -- ALL PRIVILEGES (for tables) * -- grant option for preceding privilege /yyyy -- user who granted this privilege Index: doc/src/sgml/ref/revoke.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v retrieving revision 1.35 diff -c -r1.35 revoke.sgml *** doc/src/sgml/ref/revoke.sgml 20 Oct 2005 19:18:01 -0000 1.35 --- doc/src/sgml/ref/revoke.sgml 4 Jan 2006 03:38:02 -0000 *************** *** 21,27 **** REVOKE [ GRANT OPTION FOR ] ! { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER } [,...] | ALL [ PRIVILEGES ] } ON [ TABLE ] tablename [, ...] FROM { username | GROUP groupname | PUBLIC } [, ...] --- 21,27 ---- REVOKE [ GRANT OPTION FOR ] ! { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER | TRUNCATE | VACUUM | ANALYZE } [,...] | ALL [ PRIVILEGES ] } ON [ TABLE ] tablename [, ...] FROM { username | GROUP groupname | PUBLIC } [, ...] Index: src/backend/catalog/aclchk.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/catalog/aclchk.c,v retrieving revision 1.123 diff -c -r1.123 aclchk.c *** src/backend/catalog/aclchk.c 1 Dec 2005 02:03:00 -0000 1.123 --- src/backend/catalog/aclchk.c 4 Jan 2006 03:38:02 -0000 *************** *** 1286,1291 **** --- 1286,1297 ---- return ACL_CREATE_TEMP; if (strcmp(privname, "temp") == 0) return ACL_CREATE_TEMP; + if (strcmp(privname, "truncate") == 0) + return ACL_TRUNCATE; + if (strcmp(privname, "vacuum") == 0) + return ACL_VACUUM; + if (strcmp(privname, "analyze") == 0) + return ACL_ANALYZE; ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("unrecognized privilege type \"%s\"", privname))); *************** *** 1319,1324 **** --- 1325,1336 ---- return "CREATE"; case ACL_CREATE_TEMP: return "TEMP"; + case ACL_TRUNCATE: + return "TRUNCATE"; + case ACL_VACUUM: + return "VACUUM"; + case ACL_ANALYZE: + return "ANALYZE"; default: elog(ERROR, "unrecognized privilege: %d", (int) privilege); } *************** *** 1502,1508 **** * protected in this way. Assume the view rules can take care of * themselves. */ ! if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) && IsSystemClass(classForm) && classForm->relkind != RELKIND_VIEW && !has_rolcatupdate(roleid) && --- 1514,1520 ---- * protected in this way. Assume the view rules can take care of * themselves. */ ! if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE)) && IsSystemClass(classForm) && classForm->relkind != RELKIND_VIEW && !has_rolcatupdate(roleid) && *************** *** 1511,1517 **** #ifdef ACLDEBUG elog(DEBUG2, "permission denied for system catalog update"); #endif ! mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE); } /* --- 1523,1529 ---- #ifdef ACLDEBUG elog(DEBUG2, "permission denied for system catalog update"); #endif ! mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE); } /* Index: src/backend/commands/analyze.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/analyze.c,v retrieving revision 1.90 diff -c -r1.90 analyze.c *** src/backend/commands/analyze.c 22 Nov 2005 18:17:08 -0000 1.90 --- src/backend/commands/analyze.c 4 Jan 2006 03:38:02 -0000 *************** *** 112,117 **** --- 112,118 ---- double totalrows, totaldeadrows; HeapTuple *rows; + AclResult aclresult; if (vacstmt->verbose) elevel = INFO; *************** *** 146,158 **** */ onerel = relation_open(relid, AccessShareLock); ! if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) || (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) { /* No need for a WARNING if we already complained during VACUUM */ if (!vacstmt->vacuum) ereport(WARNING, ! (errmsg("skipping \"%s\" --- only table or database owner can analyze it", RelationGetRelationName(onerel)))); relation_close(onerel, AccessShareLock); return; --- 147,160 ---- */ onerel = relation_open(relid, AccessShareLock); ! aclresult = pg_class_aclcheck(RelationGetRelid(onerel), GetUserId(), ACL_ANALYZE); ! if (!((aclresult == ACLCHECK_OK) || (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) { /* No need for a WARNING if we already complained during VACUUM */ if (!vacstmt->vacuum) ereport(WARNING, ! (errmsg("skipping \"%s\" --- only user with ANALYZE privilege or database owner can analyze it", RelationGetRelationName(onerel)))); relation_close(onerel, AccessShareLock); return; Index: src/backend/commands/tablecmds.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/tablecmds.c,v retrieving revision 1.176 diff -c -r1.176 tablecmds.c *** src/backend/commands/tablecmds.c 22 Nov 2005 18:17:09 -0000 1.176 --- src/backend/commands/tablecmds.c 4 Jan 2006 03:38:02 -0000 *************** *** 544,549 **** --- 544,550 ---- { RangeVar *rv = lfirst(cell); Relation rel; + AclResult aclresult; /* Grab exclusive lock in preparation for truncate */ rel = heap_openrv(rv, AccessExclusiveLock); *************** *** 556,564 **** 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)) ereport(ERROR, --- 557,565 ---- 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)) ereport(ERROR, Index: src/backend/commands/vacuum.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/vacuum.c,v retrieving revision 1.319 diff -c -r1.319 vacuum.c *** src/backend/commands/vacuum.c 22 Nov 2005 18:17:09 -0000 1.319 --- src/backend/commands/vacuum.c 4 Jan 2006 03:38:02 -0000 *************** *** 948,953 **** --- 948,954 ---- LockRelId onerelid; Oid toast_relid; bool result; + AclResult aclresult; /* Begin a transaction for vacuuming this relation */ StartTransactionCommand(); *************** *** 989,1008 **** /* * Open the class, get an appropriate lock on it, and check permissions. * ! * We allow the user to vacuum a table if he is superuser, the table ! * owner, or the database owner (but in the latter case, only if it's not ! * a shared relation). pg_class_ownercheck includes the superuser case. * * Note we choose to treat permissions failure as a WARNING and keep * trying to vacuum the rest of the DB --- is this appropriate? */ onerel = relation_open(relid, lmode); ! if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) || (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) { ereport(WARNING, ! (errmsg("skipping \"%s\" --- only table or database owner can vacuum it", RelationGetRelationName(onerel)))); relation_close(onerel, lmode); StrategyHintVacuum(false); --- 990,1011 ---- /* * Open the class, get an appropriate lock on it, and check permissions. * ! * We allow the user to vacuum a table if he is superuser, has the ! * VACUUM permission on the table, or the database owner (but in the ! * latter case, only if it's not a shared relation). ! * pg_class_aclcheck includes the superuser case. * * Note we choose to treat permissions failure as a WARNING and keep * trying to vacuum the rest of the DB --- is this appropriate? */ onerel = relation_open(relid, lmode); ! aclresult = pg_class_aclcheck(RelationGetRelid(onerel), GetUserId(), ACL_VACUUM); ! if (!((aclresult == ACLCHECK_OK) || (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) { ereport(WARNING, ! (errmsg("skipping \"%s\" --- only user with VACUUM privilege or database owner can vacuum it", RelationGetRelationName(onerel)))); relation_close(onerel, lmode); StrategyHintVacuum(false); Index: src/backend/parser/gram.y =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.521 diff -c -r2.521 gram.y *** src/backend/parser/gram.y 29 Dec 2005 04:53:18 -0000 2.521 --- src/backend/parser/gram.y 4 Jan 2006 03:38:02 -0000 *************** *** 3300,3305 **** --- 3300,3306 ---- privilege: SELECT { $$ = pstrdup($1); } | REFERENCES { $$ = pstrdup($1); } | CREATE { $$ = pstrdup($1); } + | ANALYZE { $$ = pstrdup($1); } | ColId { $$ = $1; } ; Index: src/backend/utils/adt/acl.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/acl.c,v retrieving revision 1.129 diff -c -r1.129 acl.c *** src/backend/utils/adt/acl.c 18 Nov 2005 02:38:23 -0000 1.129 --- src/backend/utils/adt/acl.c 4 Jan 2006 03:38:02 -0000 *************** *** 287,292 **** --- 287,301 ---- case ACL_CREATE_TEMP_CHR: read = ACL_CREATE_TEMP; break; + case ACL_TRUNCATE_CHR: + read = ACL_TRUNCATE; + break; + case ACL_VACUUM_CHR: + read = ACL_VACUUM; + break; + case ACL_ANALYZE_CHR: + read = ACL_ANALYZE; + break; default: ereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), *************** *** 1334,1339 **** --- 1343,1354 ---- return ACL_CREATE_TEMP; if (pg_strcasecmp(priv_type, "TEMPORARY") == 0) return ACL_CREATE_TEMP; + if (pg_strcasecmp(priv_type, "TRUNCATE") == 0) + return ACL_TRUNCATE; + if (pg_strcasecmp(priv_type, "VACUUM") == 0) + return ACL_VACUUM; + if (pg_strcasecmp(priv_type, "ANALYZE") == 0) + return ACL_ANALYZE; ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), *************** *** 1559,1564 **** --- 1574,1594 ---- if (pg_strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0) return ACL_GRANT_OPTION_FOR(ACL_TRIGGER); + 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, "VACUUM") == 0) + return ACL_VACUUM; + if (pg_strcasecmp(priv_type, "VACUUM WITH GRANT OPTION") == 0) + return ACL_GRANT_OPTION_FOR(ACL_VACUUM); + + if (pg_strcasecmp(priv_type, "ANALYZE") == 0) + return ACL_ANALYZE; + if (pg_strcasecmp(priv_type, "ANALYZE WITH GRANT OPTION") == 0) + return ACL_GRANT_OPTION_FOR(ACL_ANALYZE); + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("unrecognized privilege type: \"%s\"", priv_type))); Index: src/bin/pg_dump/dumputils.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v retrieving revision 1.23 diff -c -r1.23 dumputils.c *** src/bin/pg_dump/dumputils.c 3 Dec 2005 21:06:18 -0000 1.23 --- src/bin/pg_dump/dumputils.c 4 Jan 2006 03:38:02 -0000 *************** *** 580,585 **** --- 580,588 ---- CONVERT_PRIV('d', "DELETE"); CONVERT_PRIV('x', "REFERENCES"); CONVERT_PRIV('t', "TRIGGER"); + CONVERT_PRIV('e', "TRUNCATE"); + CONVERT_PRIV('V', "VACUUM"); + CONVERT_PRIV('A', "ANALYZE"); } else { Index: src/bin/psql/tab-complete.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/bin/psql/tab-complete.c,v retrieving revision 1.143 diff -c -r1.143 tab-complete.c *** src/bin/psql/tab-complete.c 18 Dec 2005 02:17:16 -0000 1.143 --- src/bin/psql/tab-complete.c 4 Jan 2006 03:38:02 -0000 *************** *** 1343,1349 **** { static const char *const list_privileg[] = {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES", ! "TRIGGER", "CREATE", "TEMPORARY", "EXECUTE", "USAGE", "ALL", NULL}; COMPLETE_WITH_LIST(list_privileg); } --- 1343,1350 ---- { static const char *const list_privileg[] = {"SELECT", "INSERT", "UPDATE", "DELETE", "RULE", "REFERENCES", ! "TRIGGER", "TRUNCATE", "VACUUM", "ANALYZE", "CREATE", ! "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.298 diff -c -r1.298 parsenodes.h *** src/include/nodes/parsenodes.h 7 Dec 2005 15:20:55 -0000 1.298 --- src/include/nodes/parsenodes.h 4 Jan 2006 03:38:02 -0000 *************** *** 47,53 **** #define ACL_USAGE (1<<8) /* for languages and namespaces */ #define ACL_CREATE (1<<9) /* for namespaces and databases */ #define ACL_CREATE_TEMP (1<<10) /* for databases */ ! #define N_ACL_RIGHTS 11 /* 1 plus the last 1<