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,
164164case ACL_KIND_CLASS :
165165whole_mask = ACL_ALL_RIGHTS_RELATION ;
166166break ;
167+ case ACL_KIND_SEQUENCE :
168+ whole_mask = ACL_ALL_RIGHTS_SEQUENCE ;
169+ break ;
167170case ACL_KIND_DATABASE :
168171whole_mask = ACL_ALL_RIGHTS_DATABASE ;
169172break ;
@@ -212,22 +215,22 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
212215if (this_privileges == 0 )
213216ereport (WARNING ,
214217(errcode (ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED ),
215- errmsg ("no privileges were granted" )));
218+ errmsg ("no privileges were granted for \"%s\"" , objname )));
216219else if (!all_privs && this_privileges != privileges )
217220ereport (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}
221224else
222225{
223226if (this_privileges == 0 )
224227ereport (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 )));
227230else if (!all_privs && this_privileges != privileges )
228231ereport (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
233236return this_privileges ;
@@ -282,9 +285,18 @@ ExecuteGrantStmt(GrantStmt *stmt)
282285 */
283286switch (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+ */
285293case 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" );
288300break ;
289301case ACL_OBJECT_DATABASE :
290302all_privileges = ACL_ALL_RIGHTS_DATABASE ;
@@ -327,6 +339,7 @@ ExecuteGrantStmt(GrantStmt *stmt)
327339{
328340istmt .all_privs = false;
329341istmt .privileges = ACL_NO_RIGHTS ;
342+
330343foreach (cell ,stmt -> privileges )
331344{
332345char * privname = strVal (lfirst (cell ));
@@ -356,6 +369,7 @@ ExecGrantStmt_oids(InternalGrant *istmt)
356369switch (istmt -> objtype )
357370{
358371case ACL_OBJECT_RELATION :
372+ case ACL_OBJECT_SEQUENCE :
359373ExecGrant_Relation (istmt );
360374break ;
361375case ACL_OBJECT_DATABASE :
@@ -395,6 +409,7 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
395409switch (objtype )
396410{
397411case ACL_OBJECT_RELATION :
412+ case ACL_OBJECT_SEQUENCE :
398413foreach (cell ,objnames )
399414{
400415Oid relOid ;
@@ -523,15 +538,15 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
523538return objects ;
524539}
525540
541+ /*
542+ *This processes both sequences and non-sequences.
543+ */
526544static void
527545ExecGrant_Relation (InternalGrant * istmt )
528546{
529547Relation relation ;
530548ListCell * cell ;
531549
532- if (istmt -> all_privs && istmt -> privileges == ACL_NO_RIGHTS )
533- istmt -> privileges = ACL_ALL_RIGHTS_RELATION ;
534-
535550relation = heap_open (RelationRelationId ,RowExclusiveLock );
536551
537552foreach (cell ,istmt -> objects )
@@ -577,6 +592,69 @@ ExecGrant_Relation(InternalGrant *istmt)
577592errmsg ("\"%s\" is a composite type" ,
578593NameStr (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)
585663aclDatum = SysCacheGetAttr (RELOID ,tuple ,Anum_pg_class_relacl ,
586664& isNull );
587665if (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 );
589669else
590670old_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 ,
594674old_acl ,ownerId ,
595675& grantorId ,& avail_goptions );
596676
@@ -600,8 +680,10 @@ ExecGrant_Relation(InternalGrant *istmt)
600680 */
601681this_privileges =
602682restrict_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 ,
605687NameStr (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 */
13381420gettext_noop ("permission denied for relation %s" ),
1421+ /* ACL_KIND_SEQUENCE */
1422+ gettext_noop ("permission denied for sequence %s" ),
13391423/* ACL_KIND_DATABASE */
13401424gettext_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 */
13621446gettext_noop ("must be owner of relation %s" ),
1447+ /* ACL_KIND_SEQUENCE */
1448+ gettext_noop ("must be owner of sequence %s" ),
13631449/* ACL_KIND_DATABASE */
13641450gettext_noop ("must be owner of database %s" ),
13651451/* ACL_KIND_PROC */
@@ -1439,6 +1525,7 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, Oid roleid,
14391525switch (objkind )
14401526{
14411527case ACL_KIND_CLASS :
1528+ case ACL_KIND_SEQUENCE :
14421529return pg_class_aclmask (table_oid ,roleid ,mask ,how );
14431530case ACL_KIND_DATABASE :
14441531return 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 ))&&
15061593IsSystemClass (classForm )&&
15071594classForm -> relkind != RELKIND_VIEW &&
15081595!has_rolcatupdate (roleid )&&
@@ -1511,7 +1598,7 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
15111598#ifdef ACLDEBUG
15121599elog (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,
15361623if (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 );
15401629aclDatum = (Datum )0 ;
15411630}
15421631else