Index: doc/src/sgml/ref/grant.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/ref/grant.sgml,v
retrieving revision 1.50
diff -c -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 10 Jan 2006 01:18:32 -0000
***************
*** 25,30 ****
--- 25,35 ----
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,265 ****
--- 265,274 ----
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,517 ****
The RULE privilege, and privileges on
! databases, tablespaces, schemas, languages, and sequences are
PostgreSQL extensions.
--- 520,526 ----
The RULE privilege, and privileges on
! databases, tablespaces, schemas, and languages are
PostgreSQL extensions.
Index: doc/src/sgml/ref/revoke.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/ref/revoke.sgml,v
retrieving revision 1.35
diff -c -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 10 Jan 2006 01:18:32 -0000
***************
*** 28,33 ****
--- 28,40 ----
[ 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 [, ...]
FROM { username | GROUP groupname | PUBLIC } [, ...]
Index: src/backend/catalog/aclchk.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v
retrieving revision 1.123
diff -c -c -r1.123 aclchk.c
*** src/backend/catalog/aclchk.c 1 Dec 2005 02:03:00 -0000 1.123
--- src/backend/catalog/aclchk.c 10 Jan 2006 01:18:34 -0000
***************
*** 164,169 ****
--- 164,172 ----
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;
***************
*** 277,319 ****
get_roleid_checked(grantee->rolname));
}
- /*
- * Convert stmt->privileges, a textual list, into an AclMode bitmask.
- */
- switch (stmt->objtype)
- {
- case ACL_OBJECT_RELATION:
- all_privileges = ACL_ALL_RIGHTS_RELATION;
- errormsg = _("invalid privilege type %s for table");
- break;
- case ACL_OBJECT_DATABASE:
- all_privileges = ACL_ALL_RIGHTS_DATABASE;
- errormsg = _("invalid privilege type %s for database");
- break;
- case ACL_OBJECT_FUNCTION:
- all_privileges = ACL_ALL_RIGHTS_FUNCTION;
- errormsg = _("invalid privilege type %s for function");
- break;
- case ACL_OBJECT_LANGUAGE:
- all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
- errormsg = _("invalid privilege type %s for language");
- break;
- case ACL_OBJECT_NAMESPACE:
- all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
- errormsg = _("invalid privilege type %s for namespace");
- break;
- case ACL_OBJECT_TABLESPACE:
- all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
- errormsg = _("invalid privilege type %s for tablespace");
- break;
- default:
- /* keep compiler quiet */
- all_privileges = ACL_NO_RIGHTS;
- errormsg = NULL;
- elog(ERROR, "unrecognized GrantStmt.objtype: %d",
- (int) stmt->objtype);
- }
-
if (stmt->privileges == NIL)
{
istmt.all_privs = true;
--- 280,285 ----
***************
*** 327,343 ****
{
istmt.all_privs = false;
istmt.privileges = ACL_NO_RIGHTS;
foreach(cell, stmt->privileges)
{
char *privname = strVal(lfirst(cell));
AclMode priv = string_to_privilege(privname);
! if (priv & ~((AclMode) all_privileges))
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_GRANT_OPERATION),
! errmsg(errormsg,
privilege_to_string(priv))));
!
istmt.privileges |= priv;
}
}
--- 293,429 ----
{
istmt.all_privs = false;
istmt.privileges = ACL_NO_RIGHTS;
+
foreach(cell, stmt->privileges)
{
char *privname = strVal(lfirst(cell));
AclMode priv = string_to_privilege(privname);
! /*
! * 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.
! */
! if (stmt->objtype == ACL_OBJECT_RELATION)
! {
! ListCell *cell2;
! bool skip_priv = false;
! bool non_seq_found = false;
!
! /*
! * GRANT can have sequences and non-sequence objects
! * in the same command, so loop over each object.
! */
! foreach(cell2, istmt.objects)
! {
! Oid relOid = lfirst_oid(cell2);
! Form_pg_class pg_class_tuple;
! HeapTuple tuple;
!
! tuple = SearchSysCache(RELOID,
! ObjectIdGetDatum(relOid),
! 0, 0, 0);
! if (!HeapTupleIsValid(tuple))
! elog(ERROR, "cache lookup failed for relation %u", relOid);
! pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
!
! if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
! {
! all_privileges = ACL_ALL_RIGHTS_SEQUENCE;
! errormsg = _("invalid privilege type %s for sequence");
! /*
! * For backward compatibility, throw just a warning
! * for invalid sequence permissions when using the
! * non-sequence GRANT syntax is used.
! */
! if (priv & ~((AclMode) ACL_ALL_RIGHTS_SEQUENCE))
! {
! ereport(WARNING,
! (errcode(ERRCODE_INVALID_GRANT_OPERATION),
! errmsg(_("invalid privilege type %s for sequence"),
! privilege_to_string(priv))));
! /* Skip assigning this priviledge */
! skip_priv = true;
! }
! }
! else
! {
! if (priv & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_GRANT_OPERATION),
! errmsg(_("invalid privilege type %s for table"),
! privilege_to_string(priv))));
! non_seq_found = true;
! }
! ReleaseSysCache(tuple);
! }
! /* If we get here, we have issued only warnings */
! if (skip_priv)
! {
! if (non_seq_found)
! /*
! * If we get here, someone has issued a command like:
! *
! * GRANT DELETE ON tab, seq TO PUBLIC
! *
! * In thise case, the DELETE is valid for the table
! * but not for the sequences. We don't want to continue
! * processing with a permission that will only partly
! * succeed, so we ERROR.
! */
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_GRANT_OPERATION),
! errmsg(_("%s privilege invalid for command mixing sequences and non-sequences"),
privilege_to_string(priv))));
! priv = 0;
! }
! }
! else
! {
! /*
! * Convert stmt->privileges, a textual list, into an AclMode bitmask.
! */
! switch (stmt->objtype)
! {
! /* ACL_OBJECT_RELATION: handled above */
! 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;
! errormsg = _("invalid privilege type %s for database");
! break;
! case ACL_OBJECT_FUNCTION:
! all_privileges = ACL_ALL_RIGHTS_FUNCTION;
! errormsg = _("invalid privilege type %s for function");
! break;
! case ACL_OBJECT_LANGUAGE:
! all_privileges = ACL_ALL_RIGHTS_LANGUAGE;
! errormsg = _("invalid privilege type %s for language");
! break;
! case ACL_OBJECT_NAMESPACE:
! all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
! errormsg = _("invalid privilege type %s for namespace");
! break;
! case ACL_OBJECT_TABLESPACE:
! all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
! errormsg = _("invalid privilege type %s for tablespace");
! break;
! default:
! /* keep compiler quiet */
! all_privileges = ACL_NO_RIGHTS;
! errormsg = NULL;
! elog(ERROR, "unrecognized GrantStmt.objtype: %d",
! (int) stmt->objtype);
! }
! if (priv & ~((AclMode) all_privileges))
! ereport(ERROR,
! (errcode(ERRCODE_INVALID_GRANT_OPERATION),
! errmsg(errormsg,
! privilege_to_string(priv))));
! }
!
istmt.privileges |= priv;
}
}
***************
*** 356,361 ****
--- 442,448 ----
switch (istmt->objtype)
{
case ACL_OBJECT_RELATION:
+ case ACL_OBJECT_SEQUENCE:
ExecGrant_Relation(istmt);
break;
case ACL_OBJECT_DATABASE:
***************
*** 395,400 ****
--- 482,488 ----
switch (objtype)
{
case ACL_OBJECT_RELATION:
+ case ACL_OBJECT_SEQUENCE:
foreach(cell, objnames)
{
Oid relOid;
***************
*** 523,537 ****
return objects;
}
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)
--- 611,625 ----
return objects;
}
+ /*
+ * This processes both sequences and non-sequences.
+ */
static void
ExecGrant_Relation(InternalGrant *istmt)
{
Relation relation;
ListCell *cell;
relation = heap_open(RelationRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
***************
*** 577,582 ****
--- 665,689 ----
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;
+
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
***************
*** 585,596 ****
aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
&isNull);
if (isNull)
! old_acl = acldefault(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,
old_acl, ownerId,
&grantorId, &avail_goptions);
--- 692,705 ----
aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
&isNull);
if (isNull)
! 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(), this_privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
***************
*** 600,607 ****
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
! istmt->all_privs, istmt->privileges,
! relOid, grantorId, ACL_KIND_CLASS,
NameStr(pg_class_tuple->relname));
/*
--- 709,718 ----
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
! 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,1341 ****
--- 1447,1454 ----
{
/* 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,1365 ****
--- 1473,1480 ----
{
/* 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,1444 ****
--- 1554,1560 ----
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,1508 ****
*
* 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.
*/
! if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
IsSystemClass(classForm) &&
classForm->relkind != RELKIND_VIEW &&
!has_rolcatupdate(roleid) &&
--- 1616,1624 ----
*
* 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. 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) &&
***************
*** 1511,1517 ****
#ifdef ACLDEBUG
elog(DEBUG2, "permission denied for system catalog update");
#endif
! mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE);
}
/*
--- 1627,1633 ----
#ifdef ACLDEBUG
elog(DEBUG2, "permission denied for system catalog update");
#endif
! mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE);
}
/*
***************
*** 1536,1542 ****
if (isNull)
{
/* No ACL, so build default ACL */
! acl = acldefault(ACL_OBJECT_RELATION, ownerId);
aclDatum = (Datum) 0;
}
else
--- 1652,1660 ----
if (isNull)
{
/* No ACL, so build default ACL */
! acl = acldefault(classForm->relkind == RELKIND_SEQUENCE ?
! ACL_OBJECT_SEQUENCE : ACL_OBJECT_RELATION,
! ownerId);
aclDatum = (Datum) 0;
}
else
Index: src/backend/catalog/pg_shdepend.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/pg_shdepend.c,v
retrieving revision 1.6
diff -c -c -r1.6 pg_shdepend.c
*** src/backend/catalog/pg_shdepend.c 1 Dec 2005 02:03:00 -0000 1.6
--- src/backend/catalog/pg_shdepend.c 10 Jan 2006 01:18:35 -0000
***************
*** 1133,1138 ****
--- 1133,1139 ----
switch (sdepForm->classid)
{
case RelationRelationId:
+ /* could be a sequence? */
istmt.objtype = ACL_OBJECT_RELATION;
break;
case DatabaseRelationId:
Index: src/backend/commands/sequence.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/sequence.c,v
retrieving revision 1.126
diff -c -c -r1.126 sequence.c
*** src/backend/commands/sequence.c 22 Nov 2005 18:17:09 -0000 1.126
--- src/backend/commands/sequence.c 10 Jan 2006 01:18:37 -0000
***************
*** 422,428 ****
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
! if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
--- 422,429 ----
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
! 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,619 ****
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
! if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
--- 614,621 ----
/* open and AccessShareLock sequence */
init_sequence(relid, &elm, &seqrel);
! 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,663 ****
/* 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)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
--- 659,666 ----
/* 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 &&
! pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for sequence %s",
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.521
diff -c -c -r2.521 gram.y
*** src/backend/parser/gram.y 29 Dec 2005 04:53:18 -0000 2.521
--- src/backend/parser/gram.y 10 Jan 2006 01:18:47 -0000
***************
*** 3322,3327 ****
--- 3322,3334 ----
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);
Index: src/backend/utils/adt/acl.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v
retrieving revision 1.129
diff -c -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 10 Jan 2006 01:18:50 -0000
***************
*** 545,550 ****
--- 545,554 ----
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;
Index: src/bin/pg_dump/dumputils.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v
retrieving revision 1.23
diff -c -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 10 Jan 2006 01:18:51 -0000
***************
*** 22,28 ****
#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,
PQExpBuffer privs, PQExpBuffer privswgo);
static char *copyAclUserName(PQExpBuffer output, char *input);
--- 22,28 ----
#define supports_grant_options(version) ((version) >= 70400)
static bool parseAclItem(const char *item, const char *type, const char *name,
! int remoteVersion, bool *is_valid_for_sequence,
PQExpBuffer grantee, PQExpBuffer grantor,
PQExpBuffer privs, PQExpBuffer privswgo);
static char *copyAclUserName(PQExpBuffer output, char *input);
***************
*** 395,404 ****
--- 395,416 ----
/* Scan individual ACL items */
for (i = 0; i < naclitems; i++)
{
+ const char *outType = type;
+ bool is_valid_for_sequence;
+
if (!parseAclItem(aclitems[i], type, name, remoteVersion,
+ &is_valid_for_sequence,
grantee, grantor, privs, privswgo))
return false;
+ /*
+ * For backward compatibility, non-SEQUENCE GRANT statements issue
+ * warnings rather than errors for invalid sequence permissions.
+ * This should only happen in pre-8.2 databases.
+ */
+ if (strcmp(outType, "SEQUENCE") == 0 && !is_valid_for_sequence)
+ outType = "TABLE";
+
if (grantor->len == 0 && owner)
printfPQExpBuffer(grantor, "%s", owner);
***************
*** 419,433 ****
: strcmp(privs->data, "ALL") != 0)
{
appendPQExpBuffer(firstsql, "REVOKE ALL ON %s %s FROM %s;\n",
! type, name,
fmtId(grantee->data));
if (privs->len > 0)
appendPQExpBuffer(firstsql, "GRANT %s ON %s %s TO %s;\n",
! privs->data, type, name,
fmtId(grantee->data));
if (privswgo->len > 0)
appendPQExpBuffer(firstsql, "GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
! privswgo->data, type, name,
fmtId(grantee->data));
}
}
--- 431,445 ----
: strcmp(privs->data, "ALL") != 0)
{
appendPQExpBuffer(firstsql, "REVOKE ALL ON %s %s FROM %s;\n",
! outType, name,
fmtId(grantee->data));
if (privs->len > 0)
appendPQExpBuffer(firstsql, "GRANT %s ON %s %s TO %s;\n",
! privs->data, outType, name,
fmtId(grantee->data));
if (privswgo->len > 0)
appendPQExpBuffer(firstsql, "GRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
! privswgo->data, outType, name,
fmtId(grantee->data));
}
}
***************
*** 444,450 ****
if (privs->len > 0)
{
appendPQExpBuffer(secondsql, "GRANT %s ON %s %s TO ",
! privs->data, type, name);
if (grantee->len == 0)
appendPQExpBuffer(secondsql, "PUBLIC;\n");
else if (strncmp(grantee->data, "group ",
--- 456,462 ----
if (privs->len > 0)
{
appendPQExpBuffer(secondsql, "GRANT %s ON %s %s TO ",
! privs->data, outType, name);
if (grantee->len == 0)
appendPQExpBuffer(secondsql, "PUBLIC;\n");
else if (strncmp(grantee->data, "group ",
***************
*** 457,463 ****
if (privswgo->len > 0)
{
appendPQExpBuffer(secondsql, "GRANT %s ON %s %s TO ",
! privswgo->data, type, name);
if (grantee->len == 0)
appendPQExpBuffer(secondsql, "PUBLIC");
else if (strncmp(grantee->data, "group ",
--- 469,475 ----
if (privswgo->len > 0)
{
appendPQExpBuffer(secondsql, "GRANT %s ON %s %s TO ",
! privswgo->data, outType, name);
if (grantee->len == 0)
appendPQExpBuffer(secondsql, "PUBLIC");
else if (strncmp(grantee->data, "group ",
***************
*** 480,489 ****
* If we didn't find any owner privs, the owner must have revoked 'em all
*/
if (!found_owner_privs && owner)
- {
appendPQExpBuffer(firstsql, "REVOKE ALL ON %s %s FROM %s;\n",
type, name, fmtId(owner));
- }
destroyPQExpBuffer(grantee);
destroyPQExpBuffer(grantor);
--- 492,499 ----
***************
*** 517,523 ****
*/
static bool
parseAclItem(const char *item, const char *type, const char *name,
! int remoteVersion,
PQExpBuffer grantee, PQExpBuffer grantor,
PQExpBuffer privs, PQExpBuffer privswgo)
{
--- 527,533 ----
*/
static bool
parseAclItem(const char *item, const char *type, const char *name,
! int remoteVersion, bool *is_valid_for_sequence,
PQExpBuffer grantee, PQExpBuffer grantor,
PQExpBuffer privs, PQExpBuffer privswgo)
{
***************
*** 530,535 ****
--- 540,547 ----
buf = strdup(item);
+ *is_valid_for_sequence = true;
+
/* user or group name is string up to = */
eqpos = copyAclUserName(grantee, buf);
if (*eqpos != '=')
***************
*** 547,554 ****
--- 559,572 ----
else
resetPQExpBuffer(grantor);
+ if (strcmp(type, "SEQUENCE") == 0 &&
+ /* SELECT, USAGE, UPDATE, ALL */
+ strspn(eqpos + 1, "rUw*") != strlen(eqpos + 1))
+ *is_valid_for_sequence = false;
+
/* privilege codes */
#define CONVERT_PRIV(code, keywd) \
+ do { \
if ((pos = strchr(eqpos + 1, code))) \
{ \
if (*(pos + 1) == '*') \
***************
*** 563,578 ****
} \
} \
else \
! all_with_go = all_without_go = false
resetPQExpBuffer(privs);
resetPQExpBuffer(privswgo);
! if (strcmp(type, "TABLE") == 0)
{
CONVERT_PRIV('a', "INSERT");
CONVERT_PRIV('r', "SELECT");
CONVERT_PRIV('R', "RULE");
if (remoteVersion >= 70200)
{
--- 581,599 ----
} \
} \
else \
! all_with_go = all_without_go = false; \
! } while (0)
resetPQExpBuffer(privs);
resetPQExpBuffer(privswgo);
! if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0)
{
CONVERT_PRIV('a', "INSERT");
CONVERT_PRIV('r', "SELECT");
CONVERT_PRIV('R', "RULE");
+ if (strcmp(type, "SEQUENCE") == 0)
+ CONVERT_PRIV('U', "USAGE");
if (remoteVersion >= 70200)
{
Index: src/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.426
diff -c -c -r1.426 pg_dump.c
*** src/bin/pg_dump/pg_dump.c 9 Jan 2006 21:16:17 -0000 1.426
--- src/bin/pg_dump/pg_dump.c 10 Jan 2006 01:18:56 -0000
***************
*** 6788,6794 ****
/* Handle the ACL here */
namecopy = strdup(fmtId(tbinfo->dobj.name));
! dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, "TABLE",
namecopy, tbinfo->dobj.name,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tbinfo->relacl);
--- 6788,6796 ----
/* Handle the ACL here */
namecopy = strdup(fmtId(tbinfo->dobj.name));
! dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
! /* Issue GRANT SEQUENCE, if applicable */
! tbinfo->relkind != RELKIND_SEQUENCE ? "TABLE" : "SEQUENCE",
namecopy, tbinfo->dobj.name,
tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
tbinfo->relacl);
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.298
diff -c -c -r1.298 parsenodes.h
*** src/include/nodes/parsenodes.h 7 Dec 2005 15:20:55 -0000 1.298
--- src/include/nodes/parsenodes.h 10 Jan 2006 01:18:58 -0000
***************
*** 884,890 ****
*/
typedef enum GrantObjectType
{
! ACL_OBJECT_RELATION, /* table, view, sequence */
ACL_OBJECT_DATABASE, /* database */
ACL_OBJECT_FUNCTION, /* function */
ACL_OBJECT_LANGUAGE, /* procedural language */
--- 884,891 ----
*/
typedef enum GrantObjectType
{
! ACL_OBJECT_RELATION, /* table, view */
! ACL_OBJECT_SEQUENCE, /* sequence */
ACL_OBJECT_DATABASE, /* database */
ACL_OBJECT_FUNCTION, /* function */
ACL_OBJECT_LANGUAGE, /* procedural language */
Index: src/include/utils/acl.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/acl.h,v
retrieving revision 1.91
diff -c -c -r1.91 acl.h
*** src/include/utils/acl.h 1 Dec 2005 02:03:01 -0000 1.91
--- src/include/utils/acl.h 10 Jan 2006 01:18:58 -0000
***************
*** 143,148 ****
--- 143,149 ----
* 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,174 ****
--- 170,176 ----
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 */