Re: [HACKERS] Inconsistent syntax in GRANT - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: [HACKERS] Inconsistent syntax in GRANT |
Date | |
Msg-id | 200601112253.k0BMr0i26727@candle.pha.pa.us Whole thread Raw |
In response to | Re: [HACKERS] Inconsistent syntax in GRANT (Tom Lane <tgl@sss.pgh.pa.us>) |
Responses |
Re: [HACKERS] Inconsistent syntax in GRANT
|
List | pgsql-patches |
Tom Lane wrote: > Bruce Momjian <pgman@candle.pha.pa.us> writes: > > Tom Lane wrote: > >> Just ignore the inapplicable permissions during pg_dump. I think you're > >> making this harder than it needs to be... > > > check all permission bits > > call object-type-specific routine > > loop over each object and set permission bits > > > so, to fix this, I would need to move the permission bit checks into > > object-type-specific routines so that I could check the permission bits > > for each object, rather than once in a single place. > > You'd have to allow the union of relation and sequence rights during the > conversion to bitmask form in ExecuteGrantStmt, and then check more > closely inside the per-object loop in ExecGrant_Relation, but that > doesn't seem like a showstopper to me. It certainly seems more pleasant > than exposing bizarre restrictions to users because we're sharing code > between the cases. Your idea of using a union of permission bits was very helpful. I was afraid I was going to have to loop over every permission bit again in the table/sequence grant permission code, but the union allowed for a very simple check in that code. It allows for better code checks and I think it behaves as expected: test=> CREATE TABLE tab(x INTEGER); CREATE TABLE test=> CREATE SEQUENCE seq; CREATE SEQUENCE test=> GRANT ALL ON seq, tab TO PUBLIC; GRANT test=> REVOKE USAGE ON seq, tab FROM PUBLIC; ERROR: invalid privilege type USAGE for table test=> REVOKE SELECT ON seq, tab FROM PUBLIC; REVOKE test=> REVOKE DELETE ON seq, tab FROM PUBLIC; WARNING: sequence "seq" only supports USAGE, SELECT, AND UPDATE WARNING: no privileges could be revoked for "seq" REVOKE and pg_dump has: GRANT USAGE,UPDATE ON SEQUENCE x TO PUBLIC; GRANT INSERT,RULE,UPDATE,REFERENCES,TRIGGER ON TABLE xx TO PUBLIC; Note I had to add the object name to the warning message so it is clear which object permission changes did succeed. I have updated the patch. -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073 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 11 Jan 2006 22:40:11 -0000 *************** *** 25,30 **** --- 25,35 ---- ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...] TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable>| PUBLIC } [, ...] [ WITH GRANT OPTION ] + GRANT { { USAGE | SELECT | UPDATE } + [,...] | ALL [ PRIVILEGES ] } + ON SEQUENCE <replaceable class="PARAMETER">sequencename</replaceable> [, ...] + TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable>| PUBLIC } [, ...] [ WITH GRANT OPTION ] + GRANT { { CREATE | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] } ON DATABASE <replaceable>dbname</replaceable> [, ...] TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable>| PUBLIC } [, ...] [ WITH GRANT OPTION ] *************** *** 260,265 **** --- 265,274 ---- also met). Essentially this allows the grantee to <quote>look up</> objects within the schema. </para> + <para> + For sequences, this privilege allows the use of the + <function>currval</function> and <function>nextval</function> functions. + </para> </listitem> </varlistentry> *************** *** 511,517 **** <para> The <literal>RULE</literal> privilege, and privileges on ! databases, tablespaces, schemas, languages, and sequences are <productname>PostgreSQL</productname> extensions. </para> </refsect1> --- 520,526 ---- <para> The <literal>RULE</literal> privilege, and privileges on ! databases, tablespaces, schemas, and languages are <productname>PostgreSQL</productname> extensions. </para> </refsect1> 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 11 Jan 2006 22:40:11 -0000 *************** *** 28,33 **** --- 28,40 ---- [ CASCADE | RESTRICT ] REVOKE [ GRANT OPTION FOR ] + { { USAGE | SELECT | UPDATE } + [,...] | ALL [ PRIVILEGES ] } + ON SEQUENCE <replaceable class="PARAMETER">sequencename</replaceable> [, ...] + FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable>| PUBLIC } [, ...] + [ CASCADE | RESTRICT ] + + REVOKE [ GRANT OPTION FOR ] { { CREATE | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] } ON DATABASE <replaceable>dbname</replaceable> [, ...] FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable>| 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 11 Jan 2006 22:40:12 -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; *************** *** 212,233 **** if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED), ! errmsg("no privileges were granted"))); else if (!all_privs && this_privileges != privileges) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED), ! errmsg("not all privileges were granted"))); } else { if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED), ! errmsg("no privileges could be revoked"))); else if (!all_privs && this_privileges != privileges) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED), ! errmsg("not all privileges could be revoked"))); } return this_privileges; --- 215,236 ---- if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_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 for \"%s\"", objname))); } else { if (this_privileges == 0) ereport(WARNING, (errcode(ERRCODE_WARNING_PRIVILEGE_NOT_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 for \"%s\"", objname))); } return this_privileges; *************** *** 282,290 **** */ 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; --- 285,302 ---- */ 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 | 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,332 **** --- 339,345 ---- { istmt.all_privs = false; istmt.privileges = ACL_NO_RIGHTS; + foreach(cell, stmt->privileges) { char *privname = strVal(lfirst(cell)); *************** *** 356,361 **** --- 369,375 ---- switch (istmt->objtype) { case ACL_OBJECT_RELATION: + case ACL_OBJECT_SEQUENCE: ExecGrant_Relation(istmt); break; case ACL_OBJECT_DATABASE: *************** *** 395,400 **** --- 409,415 ---- 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) --- 538,552 ---- 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 **** --- 592,660 ---- 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,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); --- 663,676 ---- 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)); /* --- 680,689 ---- */ 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 **** --- 1418,1425 ---- { /* 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 **** --- 1444,1451 ---- { /* 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 **** --- 1525,1531 ---- 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) && --- 1587,1595 ---- * * 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); } /* --- 1598,1604 ---- #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 --- 1623,1631 ---- 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 11 Jan 2006 22:40:12 -0000 *************** *** 1133,1140 **** switch (sdepForm->classid) { case RelationRelationId: ! istmt.objtype = ACL_OBJECT_RELATION; break; case DatabaseRelationId: istmt.objtype = ACL_OBJECT_DATABASE; break; --- 1133,1157 ---- switch (sdepForm->classid) { case RelationRelationId: ! { ! /* 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; 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 11 Jan 2006 22:40:13 -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 11 Jan 2006 22:40:20 -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 11 Jan 2006 22:40:25 -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.24 diff -c -c -r1.24 dumputils.c *** src/bin/pg_dump/dumputils.c 11 Jan 2006 21:24:30 -0000 1.24 --- src/bin/pg_dump/dumputils.c 11 Jan 2006 22:40:30 -0000 *************** *** 22,29 **** #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); static void AddAcl(PQExpBuffer aclbuf, const char *keyword); --- 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); static void AddAcl(PQExpBuffer aclbuf, const char *keyword); *************** *** 326,332 **** * * 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) * 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" --- 325,331 ---- * * 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, 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,522 **** */ static bool parseAclItem(const char *item, const char *type, const char *name, ! int remoteVersion, ! PQExpBuffer grantee, PQExpBuffer grantor, PQExpBuffer privs, PQExpBuffer privswgo) { char *buf; --- 514,520 ---- */ static bool parseAclItem(const char *item, const char *type, const char *name, ! int remoteVersion, PQExpBuffer grantee, PQExpBuffer grantor, PQExpBuffer privs, PQExpBuffer privswgo) { char *buf; *************** *** 547,552 **** --- 545,551 ---- /* privilege codes */ #define CONVERT_PRIV(code, keywd) \ + do { \ if ((pos = strchr(eqpos + 1, code))) \ { \ if (*(pos + 1) == '*') \ *************** *** 561,576 **** } \ } \ 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) { --- 560,578 ---- } \ } \ 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_backup_archiver.c =================================================================== RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v retrieving revision 1.118 diff -c -c -r1.118 pg_backup_archiver.c *** src/bin/pg_dump/pg_backup_archiver.c 22 Nov 2005 18:17:28 -0000 1.118 --- src/bin/pg_dump/pg_backup_archiver.c 11 Jan 2006 22:40:31 -0000 *************** *** 1889,1895 **** if (strcmp(ropt->schemaNames, te->namespace) != 0) return 0; } ! if ((strcmp(te->desc, "TABLE") == 0) || (strcmp(te->desc, "TABLE DATA") == 0)) { if (!ropt->selTable) return 0; --- 1889,1896 ---- if (strcmp(ropt->schemaNames, te->namespace) != 0) return 0; } ! if (strcmp(te->desc, "TABLE") == 0 || ! strcmp(te->desc, "TABLE DATA") == 0) { if (!ropt->selTable) return 0; *************** *** 2276,2283 **** const char *type = te->desc; /* Use ALTER TABLE for views and sequences */ ! if (strcmp(type, "VIEW") == 0 || ! strcmp(type, "SEQUENCE") == 0) type = "TABLE"; /* objects named by a schema and name */ --- 2277,2283 ---- const char *type = te->desc; /* Use ALTER TABLE for views and sequences */ ! if (strcmp(type, "VIEW") == 0 || strcmp(type, "SEQUENCE") == 0) type = "TABLE"; /* objects named by a schema and name */ 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 11 Jan 2006 22:40:36 -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,6804 ---- /* Handle the ACL here */ namecopy = strdup(fmtId(tbinfo->dobj.name)); ! dumpACL(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId, ! /* ! * Use GRANT SEQUENCE only when dumping a >= 8.2 database ! * because it supports the USAGE permission. ! * >= 8.2 databases still supports GRANT TABLE for loading ! * sequences from previous versions. It issues warnings ! * for invalid permissions. ! */ ! (tbinfo->relkind == RELKIND_SEQUENCE && ! fout->remoteVersion >= 80200) ! ? "SEQUENCE" : "TABLE", 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 11 Jan 2006 22:40:38 -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 11 Jan 2006 22:40:38 -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 */ Index: src/test/regress/expected/privileges.out =================================================================== RCS file: /cvsroot/pgsql/src/test/regress/expected/privileges.out,v retrieving revision 1.32 diff -c -c -r1.32 privileges.out *** src/test/regress/expected/privileges.out 15 Aug 2005 02:40:30 -0000 1.32 --- src/test/regress/expected/privileges.out 11 Jan 2006 22:40:39 -0000 *************** *** 90,96 **** COPY atest2 FROM stdin; -- fail ERROR: permission denied for relation atest2 GRANT ALL ON atest1 TO PUBLIC; -- fail ! WARNING: no privileges were granted -- checks in subquery, both ok SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); a | b --- 90,96 ---- COPY atest2 FROM stdin; -- fail ERROR: permission denied for relation atest2 GRANT ALL ON atest1 TO PUBLIC; -- fail ! 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,233 **** HINT: Only superusers may use untrusted languages. SET SESSION AUTHORIZATION regressuser1; GRANT USAGE ON LANGUAGE sql TO regressuser2; -- fail ! WARNING: no privileges were granted 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; --- 227,233 ---- HINT: Only superusers may use untrusted languages. SET SESSION AUTHORIZATION regressuser1; GRANT USAGE ON LANGUAGE sql TO regressuser2; -- fail ! 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,557 **** SET SESSION AUTHORIZATION regressuser2; GRANT SELECT ON atest4 TO regressuser3; GRANT UPDATE ON atest4 TO regressuser3; -- fail ! WARNING: no privileges were granted SET SESSION AUTHORIZATION regressuser1; REVOKE SELECT ON atest4 FROM regressuser3; -- does nothing SELECT has_table_privilege('regressuser3', 'atest4', 'SELECT'); -- true --- 551,557 ---- SET SESSION AUTHORIZATION regressuser2; GRANT SELECT ON atest4 TO regressuser3; GRANT UPDATE ON atest4 TO regressuser3; -- fail ! 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
pgsql-patches by date: