88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.123 2005/12/01 02:03:00 alvherre Exp $
11+ * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.124 2006/01/21 02:16:18 momjian Exp $
1212 *
1313 * NOTES
1414 * See acl.h.
@@ -164,6 +164,9 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
164164 case ACL_KIND_CLASS :
165165 whole_mask = ACL_ALL_RIGHTS_RELATION ;
166166 break ;
167+ case ACL_KIND_SEQUENCE :
168+ whole_mask = ACL_ALL_RIGHTS_SEQUENCE ;
169+ break ;
167170 case ACL_KIND_DATABASE :
168171 whole_mask = ACL_ALL_RIGHTS_DATABASE ;
169172 break ;
@@ -212,22 +215,22 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
212215 if (this_privileges == 0 )
213216 ereport (WARNING ,
214217 (errcode (ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED ),
215- errmsg ("no privileges were granted" )));
218+ errmsg ("no privileges were granted for \"%s\"" , objname )));
216219 else if (!all_privs && this_privileges != privileges )
217220 ereport (WARNING ,
218221 (errcode (ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED ),
219- errmsg ("not all privileges were granted" )));
222+ errmsg ("not all privileges were granted for \"%s\"" , objname )));
220223 }
221224 else
222225 {
223226 if (this_privileges == 0 )
224227 ereport (WARNING ,
225228 (errcode (ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED ),
226- errmsg ("no privileges could be revoked" )));
229+ errmsg ("no privileges could be revoked for \"%s\"" , objname )));
227230 else if (!all_privs && this_privileges != privileges )
228231 ereport (WARNING ,
229232 (errcode (ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED ),
230- errmsg ("not all privileges could be revoked" )));
233+ errmsg ("not all privileges could be revoked for \"%s\"" , objname )));
231234 }
232235
233236 return this_privileges ;
@@ -282,9 +285,18 @@ ExecuteGrantStmt(GrantStmt *stmt)
282285 */
283286 switch (stmt -> objtype )
284287 {
288+ /*
289+ * Because this might be a sequence, we test both relation
290+ * and sequence bits, and later do a more limited test
291+ * when we know the object type.
292+ */
285293 case ACL_OBJECT_RELATION :
286- all_privileges = ACL_ALL_RIGHTS_RELATION ;
287- errormsg = _ ("invalid privilege type %s for table" );
294+ all_privileges = ACL_ALL_RIGHTS_RELATION | ACL_ALL_RIGHTS_SEQUENCE ;
295+ errormsg = _ ("invalid privilege type %s for relation" );
296+ break ;
297+ case ACL_OBJECT_SEQUENCE :
298+ all_privileges = ACL_ALL_RIGHTS_SEQUENCE ;
299+ errormsg = _ ("invalid privilege type %s for sequence" );
288300 break ;
289301 case ACL_OBJECT_DATABASE :
290302 all_privileges = ACL_ALL_RIGHTS_DATABASE ;
@@ -327,6 +339,7 @@ ExecuteGrantStmt(GrantStmt *stmt)
327339 {
328340 istmt .all_privs = false;
329341 istmt .privileges = ACL_NO_RIGHTS ;
342+
330343 foreach (cell , stmt -> privileges )
331344 {
332345 char * privname = strVal (lfirst (cell ));
@@ -356,6 +369,7 @@ ExecGrantStmt_oids(InternalGrant *istmt)
356369 switch (istmt -> objtype )
357370 {
358371 case ACL_OBJECT_RELATION :
372+ case ACL_OBJECT_SEQUENCE :
359373 ExecGrant_Relation (istmt );
360374 break ;
361375 case ACL_OBJECT_DATABASE :
@@ -395,6 +409,7 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
395409 switch (objtype )
396410 {
397411 case ACL_OBJECT_RELATION :
412+ case ACL_OBJECT_SEQUENCE :
398413 foreach (cell , objnames )
399414 {
400415 Oid relOid ;
@@ -523,15 +538,15 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
523538 return objects ;
524539}
525540
541+ /*
542+ * This processes both sequences and non-sequences.
543+ */
526544static void
527545ExecGrant_Relation (InternalGrant * istmt )
528546{
529547 Relation relation ;
530548 ListCell * cell ;
531549
532- if (istmt -> all_privs && istmt -> privileges == ACL_NO_RIGHTS )
533- istmt -> privileges = ACL_ALL_RIGHTS_RELATION ;
534-
535550 relation = heap_open (RelationRelationId , RowExclusiveLock );
536551
537552 foreach (cell , istmt -> objects )
@@ -577,6 +592,69 @@ ExecGrant_Relation(InternalGrant *istmt)
577592 errmsg ("\"%s\" is a composite type" ,
578593 NameStr (pg_class_tuple -> relname ))));
579594
595+ /* Used GRANT SEQUENCE on a non-sequence? */
596+ if (istmt -> objtype == ACL_OBJECT_SEQUENCE &&
597+ pg_class_tuple -> relkind != RELKIND_SEQUENCE )
598+ ereport (ERROR ,
599+ (errcode (ERRCODE_WRONG_OBJECT_TYPE ),
600+ errmsg ("\"%s\" is not a sequence" ,
601+ NameStr (pg_class_tuple -> relname ))));
602+
603+ /* Adjust the default permissions based on whether it is a sequence */
604+ if (istmt -> all_privs && istmt -> privileges == ACL_NO_RIGHTS )
605+ {
606+ if (pg_class_tuple -> relkind == RELKIND_SEQUENCE )
607+ this_privileges = ACL_ALL_RIGHTS_SEQUENCE ;
608+ else
609+ this_privileges = ACL_ALL_RIGHTS_RELATION ;
610+ }
611+ else
612+ this_privileges = istmt -> privileges ;
613+
614+ /*
615+ * The GRANT TABLE syntax can be used for sequences and
616+ * non-sequences, so we have to look at the relkind to
617+ * determine the supported permissions. The OR of
618+ * table and sequence permissions were already checked.
619+ */
620+ if (istmt -> objtype == ACL_OBJECT_RELATION )
621+ {
622+ if (pg_class_tuple -> relkind == RELKIND_SEQUENCE )
623+ {
624+ /*
625+ * For backward compatibility, throw just a warning
626+ * for invalid sequence permissions when using the
627+ * non-sequence GRANT syntax is used.
628+ */
629+ if (this_privileges & ~((AclMode ) ACL_ALL_RIGHTS_SEQUENCE ))
630+ {
631+ /*
632+ * Mention the object name because the user needs to
633+ * know which operations succeeded. This is required
634+ * because WARNING allows the command to continue.
635+ */
636+ ereport (WARNING ,
637+ (errcode (ERRCODE_INVALID_GRANT_OPERATION ),
638+ errmsg ("sequence \"%s\" only supports USAGE, SELECT, and UPDATE" ,
639+ NameStr (pg_class_tuple -> relname ))));
640+ this_privileges &= (AclMode ) ACL_ALL_RIGHTS_SEQUENCE ;
641+ }
642+ }
643+ else
644+ {
645+ if (this_privileges & ~((AclMode ) ACL_ALL_RIGHTS_RELATION ))
646+ /*
647+ * USAGE is the only permission supported by sequences
648+ * but not by non-sequences. Don't mention the object
649+ * name because we didn't in the combined TABLE |
650+ * SEQUENCE check.
651+ */
652+ ereport (ERROR ,
653+ (errcode (ERRCODE_INVALID_GRANT_OPERATION ),
654+ errmsg ("invalid privilege type USAGE for table" )));
655+ }
656+ }
657+
580658 /*
581659 * Get owner ID and working copy of existing ACL. If there's no ACL,
582660 * substitute the proper default.
@@ -585,12 +663,14 @@ ExecGrant_Relation(InternalGrant *istmt)
585663 aclDatum = SysCacheGetAttr (RELOID , tuple , Anum_pg_class_relacl ,
586664 & isNull );
587665 if (isNull )
588- old_acl = acldefault (ACL_OBJECT_RELATION , ownerId );
666+ old_acl = acldefault (pg_class_tuple -> relkind == RELKIND_SEQUENCE ?
667+ ACL_OBJECT_SEQUENCE : ACL_OBJECT_RELATION ,
668+ ownerId );
589669 else
590670 old_acl = DatumGetAclPCopy (aclDatum );
591671
592672 /* Determine ID to do the grant as, and available grant options */
593- select_best_grantor (GetUserId (), istmt -> privileges ,
673+ select_best_grantor (GetUserId (), this_privileges ,
594674 old_acl , ownerId ,
595675 & grantorId , & avail_goptions );
596676
@@ -600,8 +680,10 @@ ExecGrant_Relation(InternalGrant *istmt)
600680 */
601681 this_privileges =
602682 restrict_and_check_grant (istmt -> is_grant , avail_goptions ,
603- istmt -> all_privs , istmt -> privileges ,
604- relOid , grantorId , ACL_KIND_CLASS ,
683+ istmt -> all_privs , this_privileges ,
684+ relOid , grantorId ,
685+ pg_class_tuple -> relkind == RELKIND_SEQUENCE
686+ ? ACL_KIND_SEQUENCE : ACL_KIND_CLASS ,
605687 NameStr (pg_class_tuple -> relname ));
606688
607689 /*
@@ -1336,6 +1418,8 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
13361418{
13371419 /* ACL_KIND_CLASS */
13381420 gettext_noop ("permission denied for relation %s" ),
1421+ /* ACL_KIND_SEQUENCE */
1422+ gettext_noop ("permission denied for sequence %s" ),
13391423 /* ACL_KIND_DATABASE */
13401424 gettext_noop ("permission denied for database %s" ),
13411425 /* ACL_KIND_PROC */
@@ -1360,6 +1444,8 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
13601444{
13611445 /* ACL_KIND_CLASS */
13621446 gettext_noop ("must be owner of relation %s" ),
1447+ /* ACL_KIND_SEQUENCE */
1448+ gettext_noop ("must be owner of sequence %s" ),
13631449 /* ACL_KIND_DATABASE */
13641450 gettext_noop ("must be owner of database %s" ),
13651451 /* ACL_KIND_PROC */
@@ -1439,6 +1525,7 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, Oid roleid,
14391525 switch (objkind )
14401526 {
14411527 case ACL_KIND_CLASS :
1528+ case ACL_KIND_SEQUENCE :
14421529 return pg_class_aclmask (table_oid , roleid , mask , how );
14431530 case ACL_KIND_DATABASE :
14441531 return pg_database_aclmask (table_oid , roleid , mask , how );
@@ -1500,9 +1587,9 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
15001587 *
15011588 * As of 7.4 we have some updatable system views; those shouldn't be
15021589 * protected in this way. Assume the view rules can take care of
1503- * themselves.
1590+ * themselves. ACL_USAGE is if we ever have system sequences.
15041591 */
1505- if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE )) &&
1592+ if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE )) &&
15061593 IsSystemClass (classForm ) &&
15071594 classForm -> relkind != RELKIND_VIEW &&
15081595 !has_rolcatupdate (roleid ) &&
@@ -1511,7 +1598,7 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
15111598#ifdef ACLDEBUG
15121599 elog (DEBUG2 , "permission denied for system catalog update" );
15131600#endif
1514- mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE );
1601+ mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE );
15151602 }
15161603
15171604 /*
@@ -1536,7 +1623,9 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
15361623 if (isNull )
15371624 {
15381625 /* No ACL, so build default ACL */
1539- acl = acldefault (ACL_OBJECT_RELATION , ownerId );
1626+ acl = acldefault (classForm -> relkind == RELKIND_SEQUENCE ?
1627+ ACL_OBJECT_SEQUENCE : ACL_OBJECT_RELATION ,
1628+ ownerId );
15401629 aclDatum = (Datum ) 0 ;
15411630 }
15421631 else
0 commit comments