diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index bb9571abd8..e5ea4bb144 100644
--- a/doc/src/sgml/ref/grant.sgml
+++ b/doc/src/sgml/ref/grant.sgml
@@ -1,5 +1,5 @@
@@ -25,6 +25,11 @@ GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER }
ON [ TABLE ] tablename [, ...]
TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+GRANT { { USAGE | SELECT | UPDATE }
+ [,...] | ALL [ PRIVILEGES ] }
+ ON SEQUENCE sequencename [, ...]
+ TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+
GRANT { { CREATE | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
ON DATABASE dbname [, ...]
TO { username | GROUP groupname | PUBLIC } [, ...] [ WITH GRANT OPTION ]
@@ -260,6 +265,10 @@ GRANT role [, ...]
also met). Essentially this allows the grantee to look up>
objects within the schema.
+
+ For sequences, this privilege allows the use of the
+ currval and nextval functions.
+
@@ -511,7 +520,7 @@ GRANT privileges
The RULE privilege, and privileges on
- databases, tablespaces, schemas, languages, and sequences are
+ databases, tablespaces, schemas, and languages are
PostgreSQL extensions.
diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml
index 68c69f8814..f09642a7b5 100644
--- a/doc/src/sgml/ref/revoke.sgml
+++ b/doc/src/sgml/ref/revoke.sgml
@@ -1,5 +1,5 @@
@@ -27,6 +27,13 @@ REVOKE [ GRANT OPTION FOR ]
FROM { username | GROUP groupname | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
+REVOKE [ GRANT OPTION FOR ]
+ { { USAGE | SELECT | UPDATE }
+ [,...] | ALL [ PRIVILEGES ] }
+ ON SEQUENCE sequencename [, ...]
+ FROM { username | GROUP groupname | PUBLIC } [, ...]
+ [ CASCADE | RESTRICT ]
+
REVOKE [ GRANT OPTION FOR ]
{ { CREATE | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
ON DATABASE dbname [, ...]
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 643d31c199..dbdf523dd5 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.123 2005/12/01 02:03:00 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.124 2006/01/21 02:16:18 momjian Exp $
*
* NOTES
* See acl.h.
@@ -164,6 +164,9 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
case ACL_KIND_CLASS:
whole_mask = ACL_ALL_RIGHTS_RELATION;
break;
+ case ACL_KIND_SEQUENCE:
+ whole_mask = ACL_ALL_RIGHTS_SEQUENCE;
+ break;
case ACL_KIND_DATABASE:
whole_mask = ACL_ALL_RIGHTS_DATABASE;
break;
@@ -212,22 +215,22 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
if (this_privileges == 0)
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
- errmsg("no privileges were granted")));
+ errmsg("no privileges were granted for \"%s\"", objname)));
else if (!all_privs && this_privileges != privileges)
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED),
- errmsg("not all privileges were granted")));
+ errmsg("not all privileges were granted for \"%s\"", objname)));
}
else
{
if (this_privileges == 0)
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
- errmsg("no privileges could be revoked")));
+ errmsg("no privileges could be revoked for \"%s\"", objname)));
else if (!all_privs && this_privileges != privileges)
ereport(WARNING,
(errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED),
- errmsg("not all privileges could be revoked")));
+ errmsg("not all privileges could be revoked for \"%s\"", objname)));
}
return this_privileges;
@@ -282,9 +285,18 @@ ExecuteGrantStmt(GrantStmt *stmt)
*/
switch (stmt->objtype)
{
+ /*
+ * Because this might be a sequence, we test both relation
+ * and sequence bits, and later do a more limited test
+ * when we know the object type.
+ */
case ACL_OBJECT_RELATION:
- all_privileges = ACL_ALL_RIGHTS_RELATION;
- errormsg = _("invalid privilege type %s for table");
+ all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE;
+ errormsg = _("invalid privilege type %s for relation");
+ break;
+ case ACL_OBJECT_SEQUENCE:
+ all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ errormsg = _("invalid privilege type %s for sequence");
break;
case ACL_OBJECT_DATABASE:
all_privileges = ACL_ALL_RIGHTS_DATABASE;
@@ -327,6 +339,7 @@ ExecuteGrantStmt(GrantStmt *stmt)
{
istmt.all_privs = false;
istmt.privileges = ACL_NO_RIGHTS;
+
foreach(cell, stmt->privileges)
{
char *privname = strVal(lfirst(cell));
@@ -356,6 +369,7 @@ ExecGrantStmt_oids(InternalGrant *istmt)
switch (istmt->objtype)
{
case ACL_OBJECT_RELATION:
+ case ACL_OBJECT_SEQUENCE:
ExecGrant_Relation(istmt);
break;
case ACL_OBJECT_DATABASE:
@@ -395,6 +409,7 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
switch (objtype)
{
case ACL_OBJECT_RELATION:
+ case ACL_OBJECT_SEQUENCE:
foreach(cell, objnames)
{
Oid relOid;
@@ -523,15 +538,15 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
return objects;
}
+/*
+ * This processes both sequences and non-sequences.
+ */
static void
ExecGrant_Relation(InternalGrant *istmt)
{
Relation relation;
ListCell *cell;
- if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
- istmt->privileges = ACL_ALL_RIGHTS_RELATION;
-
relation = heap_open(RelationRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
@@ -577,6 +592,69 @@ ExecGrant_Relation(InternalGrant *istmt)
errmsg("\"%s\" is a composite type",
NameStr(pg_class_tuple->relname))));
+ /* Used GRANT SEQUENCE on a non-sequence? */
+ if (istmt->objtype == ACL_OBJECT_SEQUENCE &&
+ pg_class_tuple->relkind != RELKIND_SEQUENCE)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a sequence",
+ NameStr(pg_class_tuple->relname))));
+
+ /* Adjust the default permissions based on whether it is a sequence */
+ if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
+ {
+ if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
+ this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
+ else
+ this_privileges = ACL_ALL_RIGHTS_RELATION;
+ }
+ else
+ this_privileges = istmt->privileges;
+
+ /*
+ * The GRANT TABLE syntax can be used for sequences and
+ * non-sequences, so we have to look at the relkind to
+ * determine the supported permissions. The OR of
+ * table and sequence permissions were already checked.
+ */
+ if (istmt->objtype == ACL_OBJECT_RELATION)
+ {
+ if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
+ {
+ /*
+ * For backward compatibility, throw just a warning
+ * for invalid sequence permissions when using the
+ * non-sequence GRANT syntax is used.
+ */
+ if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
+ {
+ /*
+ * Mention the object name because the user needs to
+ * know which operations succeeded. This is required
+ * because WARNING allows the command to continue.
+ */
+ ereport(WARNING,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("sequence \"%s\" only supports USAGE, SELECT, and UPDATE",
+ NameStr(pg_class_tuple->relname))));
+ this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
+ }
+ }
+ else
+ {
+ if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
+ /*
+ * USAGE is the only permission supported by sequences
+ * but not by non-sequences. Don't mention the object
+ * name because we didn't in the combined TABLE |
+ * SEQUENCE check.
+ */
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ errmsg("invalid privilege type USAGE for table")));
+ }
+ }
+
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
@@ -585,12 +663,14 @@ ExecGrant_Relation(InternalGrant *istmt)
aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
&isNull);
if (isNull)
- old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
+ old_acl = acldefault(pg_class_tuple->relkind == RELKIND_SEQUENCE ?
+ ACL_OBJECT_SEQUENCE : ACL_OBJECT_RELATION,
+ ownerId);
else
old_acl = DatumGetAclPCopy(aclDatum);
/* Determine ID to do the grant as, and available grant options */
- select_best_grantor(GetUserId(), istmt->privileges,
+ select_best_grantor(GetUserId(), this_privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
@@ -600,8 +680,10 @@ ExecGrant_Relation(InternalGrant *istmt)
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
- istmt->all_privs, istmt->privileges,
- relOid, grantorId, ACL_KIND_CLASS,
+ istmt->all_privs, this_privileges,
+ relOid, grantorId,
+ pg_class_tuple->relkind == RELKIND_SEQUENCE
+ ? ACL_KIND_SEQUENCE : ACL_KIND_CLASS,
NameStr(pg_class_tuple->relname));
/*
@@ -1336,6 +1418,8 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
{
/* ACL_KIND_CLASS */
gettext_noop("permission denied for relation %s"),
+ /* ACL_KIND_SEQUENCE */
+ gettext_noop("permission denied for sequence %s"),
/* ACL_KIND_DATABASE */
gettext_noop("permission denied for database %s"),
/* ACL_KIND_PROC */
@@ -1360,6 +1444,8 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
{
/* ACL_KIND_CLASS */
gettext_noop("must be owner of relation %s"),
+ /* ACL_KIND_SEQUENCE */
+ gettext_noop("must be owner of sequence %s"),
/* ACL_KIND_DATABASE */
gettext_noop("must be owner of database %s"),
/* ACL_KIND_PROC */
@@ -1439,6 +1525,7 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, Oid roleid,
switch (objkind)
{
case ACL_KIND_CLASS:
+ case ACL_KIND_SEQUENCE:
return pg_class_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_DATABASE:
return pg_database_aclmask(table_oid, roleid, mask, how);
@@ -1500,9 +1587,9 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
*
* As of 7.4 we have some updatable system views; those shouldn't be
* protected in this way. Assume the view rules can take care of
- * themselves.
+ * themselves. ACL_USAGE is if we ever have system sequences.
*/
- if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
+ if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE)) &&
IsSystemClass(classForm) &&
classForm->relkind != RELKIND_VIEW &&
!has_rolcatupdate(roleid) &&
@@ -1511,7 +1598,7 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
#ifdef ACLDEBUG
elog(DEBUG2, "permission denied for system catalog update");
#endif
- mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE);
+ mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE);
}
/*
@@ -1536,7 +1623,9 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
if (isNull)
{
/* No ACL, so build default ACL */
- acl = acldefault(ACL_OBJECT_RELATION, ownerId);
+ acl = acldefault(classForm->relkind == RELKIND_SEQUENCE ?
+ ACL_OBJECT_SEQUENCE : ACL_OBJECT_RELATION,
+ ownerId);
aclDatum = (Datum) 0;
}
else
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index faa64c22fc..e57a22858f 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.6 2005/12/01 02:03:00 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.7 2006/01/21 02:16:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1133,8 +1133,25 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
switch (sdepForm->classid)
{
case RelationRelationId:
- istmt.objtype = ACL_OBJECT_RELATION;
+ {
+ /* is it a sequence or non-sequence? */
+ Form_pg_class pg_class_tuple;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache(RELOID,
+ ObjectIdGetDatum(sdepForm->objid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for relation %u",
+ sdepForm->objid);
+ pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
+ if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
+ istmt.objtype = ACL_OBJECT_SEQUENCE;
+ else
+ istmt.objtype = ACL_OBJECT_RELATION;
+ ReleaseSysCache(tuple);
break;
+ }
case DatabaseRelationId:
istmt.objtype = ACL_OBJECT_DATABASE;
break;
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 9c1efe856c..53244cbedc 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.126 2005/11/22 18:17:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.127 2006/01/21 02:16:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -422,7 +422,8 @@ nextval_internal(Oid relid)
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
- if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
+ if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK &&
+ pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
@@ -613,7 +614,8 @@ currval_oid(PG_FUNCTION_ARGS)
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
- if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
+ if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK &&
+ pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
@@ -657,7 +659,8 @@ lastval(PG_FUNCTION_ARGS)
/* nextval() must have already been called for this sequence */
Assert(last_used_seq->increment != 0);
- if (pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
+ if (pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK &&
+ pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ceb7143ce2..41b22d811c 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.521 2005/12/29 04:53:18 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.522 2006/01/21 02:16:19 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -3322,6 +3322,13 @@ privilege_target:
n->objs = $2;
$$ = n;
}
+ | SEQUENCE qualified_name_list
+ {
+ PrivTarget *n = makeNode(PrivTarget);
+ n->objtype = ACL_OBJECT_SEQUENCE;
+ n->objs = $2;
+ $$ = n;
+ }
| FUNCTION function_with_argtypes_list
{
PrivTarget *n = makeNode(PrivTarget);
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 9282c417d0..2232e042a3 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.129 2005/11/18 02:38:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.130 2006/01/21 02:16:19 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -545,6 +545,10 @@ acldefault(GrantObjectType objtype, Oid ownerId)
world_default = ACL_NO_RIGHTS;
owner_default = ACL_ALL_RIGHTS_RELATION;
break;
+ case ACL_OBJECT_SEQUENCE:
+ world_default = ACL_NO_RIGHTS;
+ owner_default = ACL_ALL_RIGHTS_SEQUENCE;
+ break;
case ACL_OBJECT_DATABASE:
world_default = ACL_CREATE_TEMP; /* not NO_RIGHTS! */
owner_default = ACL_ALL_RIGHTS_DATABASE;
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index a4d1fa4e18..7bdce3bc2e 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.24 2006/01/11 21:24:30 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.25 2006/01/21 02:16:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,8 +22,7 @@
#define supports_grant_options(version) ((version) >= 70400)
static bool parseAclItem(const char *item, const char *type, const char *name,
- int remoteVersion,
- PQExpBuffer grantee, PQExpBuffer grantor,
+ int remoteVersion, PQExpBuffer grantee, PQExpBuffer grantor,
PQExpBuffer privs, PQExpBuffer privswgo);
static char *copyAclUserName(PQExpBuffer output, char *input);
static void AddAcl(PQExpBuffer aclbuf, const char *keyword);
@@ -326,7 +325,7 @@ parsePGArray(const char *atext, char ***itemarray, int *nitems)
*
* name: the object name, in the form to use in the commands (already quoted)
* type: the object type (as seen in GRANT command: must be one of
- * TABLE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, or TABLESPACE)
+ * TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, or TABLESPACE)
* acls: the ACL string fetched from the database
* owner: username of object owner (will be passed through fmtId); can be
* NULL or empty string to indicate "no owner known"
@@ -515,8 +514,7 @@ buildACLCommands(const char *name, const char *type,
*/
static bool
parseAclItem(const char *item, const char *type, const char *name,
- int remoteVersion,
- PQExpBuffer grantee, PQExpBuffer grantor,
+ int remoteVersion, PQExpBuffer grantee, PQExpBuffer grantor,
PQExpBuffer privs, PQExpBuffer privswgo)
{
char *buf;
@@ -547,6 +545,7 @@ parseAclItem(const char *item, const char *type, const char *name,
/* privilege codes */
#define CONVERT_PRIV(code, keywd) \
+do { \
if ((pos = strchr(eqpos + 1, code))) \
{ \
if (*(pos + 1) == '*') \
@@ -561,29 +560,38 @@ parseAclItem(const char *item, const char *type, const char *name,
} \
} \
else \
- all_with_go = all_without_go = false
+ all_with_go = all_without_go = false; \
+} while (0)
resetPQExpBuffer(privs);
resetPQExpBuffer(privswgo);
- if (strcmp(type, "TABLE") == 0)
+ if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0)
{
- CONVERT_PRIV('a', "INSERT");
CONVERT_PRIV('r', "SELECT");
- CONVERT_PRIV('R', "RULE");
-
- if (remoteVersion >= 70200)
- {
- CONVERT_PRIV('w', "UPDATE");
- CONVERT_PRIV('d', "DELETE");
- CONVERT_PRIV('x', "REFERENCES");
- CONVERT_PRIV('t', "TRIGGER");
- }
+
+ if (strcmp(type, "SEQUENCE") == 0)
+ /* sequence only */
+ CONVERT_PRIV('U', "USAGE");
else
{
+ /* table only */
+ CONVERT_PRIV('a', "INSERT");
+ CONVERT_PRIV('R', "RULE");
+ if (remoteVersion >= 70200)
+ {
+ CONVERT_PRIV('d', "DELETE");
+ CONVERT_PRIV('x', "REFERENCES");
+ CONVERT_PRIV('t', "TRIGGER");
+ }
+ }
+
+ /* UPDATE */
+ if (remoteVersion >= 70200 || strcmp(type, "SEQUENCE") == 0)
+ CONVERT_PRIV('w', "UPDATE");
+ else
/* 7.0 and 7.1 have a simpler worldview */
CONVERT_PRIV('w', "UPDATE,DELETE");
- }
}
else if (strcmp(type, "FUNCTION") == 0)
CONVERT_PRIV('X', "EXECUTE");
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index a45018533e..4a3116245e 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.118 2005/11/22 18:17:28 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.119 2006/01/21 02:16:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1889,7 +1889,8 @@ _tocEntryRequired(TocEntry *te, RestoreOptions *ropt, bool include_acls)
if (strcmp(ropt->schemaNames, te->namespace) != 0)
return 0;
}
- if ((strcmp(te->desc, "TABLE") == 0) || (strcmp(te->desc, "TABLE DATA") == 0))
+ if (strcmp(te->desc, "TABLE") == 0 ||
+ strcmp(te->desc, "TABLE DATA") == 0)
{
if (!ropt->selTable)
return 0;
@@ -2276,8 +2277,7 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
const char *type = te->desc;
/* Use ALTER TABLE for views and sequences */
- if (strcmp(type, "VIEW") == 0 ||
- strcmp(type, "SEQUENCE") == 0)
+ if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0)
type = "TABLE";
/* objects named by a schema and name */
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 1ae6730ad0..3dffc9b3f4 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.426 2006/01/09 21:16:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.427 2006/01/21 02:16:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -6788,7 +6788,8 @@ dumpTable(Archive *fout, TableInfo *tbinfo)
/* Handle the ACL here */
namecopy = strdup(fmtId(tbinfo->dobj.name));
- dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
+ dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
+ (tbinfo->relkind == RELKIND_SEQUENCE) ? "SEQUENCE" : "TABLE",
namecopy, tbinfo->dobj.name,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tbinfo->relacl);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ba39652795..e738ec2b03 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.298 2005/12/07 15:20:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.299 2006/01/21 02:16:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -884,7 +884,8 @@ typedef struct AlterDomainStmt
*/
typedef enum GrantObjectType
{
- ACL_OBJECT_RELATION, /* table, view, sequence */
+ ACL_OBJECT_RELATION, /* table, view */
+ ACL_OBJECT_SEQUENCE, /* sequence */
ACL_OBJECT_DATABASE, /* database */
ACL_OBJECT_FUNCTION, /* function */
ACL_OBJECT_LANGUAGE, /* procedural language */
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 8e6cb95d25..4967970b04 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.91 2005/12/01 02:03:01 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.92 2006/01/21 02:16:21 momjian Exp $
*
* NOTES
* An ACL array is simply an array of AclItems, representing the union
@@ -143,6 +143,7 @@ typedef ArrayType Acl;
* Bitmasks defining "all rights" for each supported object type
*/
#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)
#define ACL_ALL_RIGHTS_FUNCTION (ACL_EXECUTE)
#define ACL_ALL_RIGHTS_LANGUAGE (ACL_USAGE)
@@ -169,6 +170,7 @@ typedef enum
typedef enum AclObjectKind
{
ACL_KIND_CLASS, /* pg_class */
+ ACL_KIND_SEQUENCE, /* pg_sequence */
ACL_KIND_DATABASE, /* pg_database */
ACL_KIND_PROC, /* pg_proc */
ACL_KIND_OPER, /* pg_operator */
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 354f5b2984..a18116a289 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -90,7 +90,7 @@ ERROR: permission denied for relation atest2
COPY atest2 FROM stdin; -- fail
ERROR: permission denied for relation atest2
GRANT ALL ON atest1 TO PUBLIC; -- fail
-WARNING: no privileges were granted
+WARNING: no privileges were granted for "atest1"
-- checks in subquery, both ok
SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) );
a | b
@@ -227,7 +227,7 @@ ERROR: language "c" is not trusted
HINT: Only superusers may use untrusted languages.
SET SESSION AUTHORIZATION regressuser1;
GRANT USAGE ON LANGUAGE sql TO regressuser2; -- fail
-WARNING: no privileges were granted
+WARNING: no privileges were granted for "sql"
CREATE FUNCTION testfunc1(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql;
CREATE FUNCTION testfunc2(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql;
REVOKE ALL ON FUNCTION testfunc1(int), testfunc2(int) FROM PUBLIC;
@@ -551,7 +551,7 @@ GRANT SELECT ON atest4 TO GROUP regressgroup1 WITH GRANT OPTION;
SET SESSION AUTHORIZATION regressuser2;
GRANT SELECT ON atest4 TO regressuser3;
GRANT UPDATE ON atest4 TO regressuser3; -- fail
-WARNING: no privileges were granted
+WARNING: no privileges were granted for "atest4"
SET SESSION AUTHORIZATION regressuser1;
REVOKE SELECT ON atest4 FROM regressuser3; -- does nothing
SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- true