8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
* NOTES
14
14
* See acl.h.
@@ -164,6 +164,9 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
164
164
case ACL_KIND_CLASS :
165
165
whole_mask = ACL_ALL_RIGHTS_RELATION ;
166
166
break ;
167
+ case ACL_KIND_SEQUENCE :
168
+ whole_mask = ACL_ALL_RIGHTS_SEQUENCE ;
169
+ break ;
167
170
case ACL_KIND_DATABASE :
168
171
whole_mask = ACL_ALL_RIGHTS_DATABASE ;
169
172
break ;
@@ -212,22 +215,22 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
212
215
if (this_privileges == 0 )
213
216
ereport (WARNING ,
214
217
(errcode (ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED ),
215
- errmsg ("no privileges were granted" )));
218
+ errmsg ("no privileges were granted for \"%s\"" , objname )));
216
219
else if (!all_privs && this_privileges != privileges )
217
220
ereport (WARNING ,
218
221
(errcode (ERRCODE_WARNING_PRIVILEGE_NOT_GRANTED ),
219
- errmsg ("not all privileges were granted" )));
222
+ errmsg ("not all privileges were granted for \"%s\"" , objname )));
220
223
}
221
224
else
222
225
{
223
226
if (this_privileges == 0 )
224
227
ereport (WARNING ,
225
228
(errcode (ERRCODE_WARNING_PRIVILEGE_NOT_REVOKED ),
226
- errmsg ("no privileges could be revoked" )));
229
+ errmsg ("no privileges could be revoked for \"%s\"" , objname )));
227
230
else if (!all_privs && this_privileges != privileges )
228
231
ereport (WARNING ,
229
232
(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 )));
231
234
}
232
235
233
236
return this_privileges ;
@@ -282,9 +285,18 @@ ExecuteGrantStmt(GrantStmt *stmt)
282
285
*/
283
286
switch (stmt -> objtype )
284
287
{
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
+ */
285
293
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" );
288
300
break ;
289
301
case ACL_OBJECT_DATABASE :
290
302
all_privileges = ACL_ALL_RIGHTS_DATABASE ;
@@ -327,6 +339,7 @@ ExecuteGrantStmt(GrantStmt *stmt)
327
339
{
328
340
istmt .all_privs = false;
329
341
istmt .privileges = ACL_NO_RIGHTS ;
342
+
330
343
foreach (cell , stmt -> privileges )
331
344
{
332
345
char * privname = strVal (lfirst (cell ));
@@ -356,6 +369,7 @@ ExecGrantStmt_oids(InternalGrant *istmt)
356
369
switch (istmt -> objtype )
357
370
{
358
371
case ACL_OBJECT_RELATION :
372
+ case ACL_OBJECT_SEQUENCE :
359
373
ExecGrant_Relation (istmt );
360
374
break ;
361
375
case ACL_OBJECT_DATABASE :
@@ -395,6 +409,7 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
395
409
switch (objtype )
396
410
{
397
411
case ACL_OBJECT_RELATION :
412
+ case ACL_OBJECT_SEQUENCE :
398
413
foreach (cell , objnames )
399
414
{
400
415
Oid relOid ;
@@ -523,15 +538,15 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
523
538
return objects ;
524
539
}
525
540
541
+ /*
542
+ * This processes both sequences and non-sequences.
543
+ */
526
544
static void
527
545
ExecGrant_Relation (InternalGrant * istmt )
528
546
{
529
547
Relation relation ;
530
548
ListCell * cell ;
531
549
532
- if (istmt -> all_privs && istmt -> privileges == ACL_NO_RIGHTS )
533
- istmt -> privileges = ACL_ALL_RIGHTS_RELATION ;
534
-
535
550
relation = heap_open (RelationRelationId , RowExclusiveLock );
536
551
537
552
foreach (cell , istmt -> objects )
@@ -577,6 +592,69 @@ ExecGrant_Relation(InternalGrant *istmt)
577
592
errmsg ("\"%s\" is a composite type" ,
578
593
NameStr (pg_class_tuple -> relname ))));
579
594
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
+
580
658
/*
581
659
* Get owner ID and working copy of existing ACL. If there's no ACL,
582
660
* substitute the proper default.
@@ -585,12 +663,14 @@ ExecGrant_Relation(InternalGrant *istmt)
585
663
aclDatum = SysCacheGetAttr (RELOID , tuple , Anum_pg_class_relacl ,
586
664
& isNull );
587
665
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 );
589
669
else
590
670
old_acl = DatumGetAclPCopy (aclDatum );
591
671
592
672
/* 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 ,
594
674
old_acl , ownerId ,
595
675
& grantorId , & avail_goptions );
596
676
@@ -600,8 +680,10 @@ ExecGrant_Relation(InternalGrant *istmt)
600
680
*/
601
681
this_privileges =
602
682
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 ,
605
687
NameStr (pg_class_tuple -> relname ));
606
688
607
689
/*
@@ -1336,6 +1418,8 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
1336
1418
{
1337
1419
/* ACL_KIND_CLASS */
1338
1420
gettext_noop ("permission denied for relation %s" ),
1421
+ /* ACL_KIND_SEQUENCE */
1422
+ gettext_noop ("permission denied for sequence %s" ),
1339
1423
/* ACL_KIND_DATABASE */
1340
1424
gettext_noop ("permission denied for database %s" ),
1341
1425
/* ACL_KIND_PROC */
@@ -1360,6 +1444,8 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
1360
1444
{
1361
1445
/* ACL_KIND_CLASS */
1362
1446
gettext_noop ("must be owner of relation %s" ),
1447
+ /* ACL_KIND_SEQUENCE */
1448
+ gettext_noop ("must be owner of sequence %s" ),
1363
1449
/* ACL_KIND_DATABASE */
1364
1450
gettext_noop ("must be owner of database %s" ),
1365
1451
/* ACL_KIND_PROC */
@@ -1439,6 +1525,7 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, Oid roleid,
1439
1525
switch (objkind )
1440
1526
{
1441
1527
case ACL_KIND_CLASS :
1528
+ case ACL_KIND_SEQUENCE :
1442
1529
return pg_class_aclmask (table_oid , roleid , mask , how );
1443
1530
case ACL_KIND_DATABASE :
1444
1531
return pg_database_aclmask (table_oid , roleid , mask , how );
@@ -1500,9 +1587,9 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
1500
1587
*
1501
1588
* As of 7.4 we have some updatable system views; those shouldn't be
1502
1589
* 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.
1504
1591
*/
1505
- if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE )) &&
1592
+ if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE )) &&
1506
1593
IsSystemClass (classForm ) &&
1507
1594
classForm -> relkind != RELKIND_VIEW &&
1508
1595
!has_rolcatupdate (roleid ) &&
@@ -1511,7 +1598,7 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
1511
1598
#ifdef ACLDEBUG
1512
1599
elog (DEBUG2 , "permission denied for system catalog update" );
1513
1600
#endif
1514
- mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE );
1601
+ mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE | ACL_USAGE );
1515
1602
}
1516
1603
1517
1604
/*
@@ -1536,7 +1623,9 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
1536
1623
if (isNull )
1537
1624
{
1538
1625
/* 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 );
1540
1629
aclDatum = (Datum ) 0 ;
1541
1630
}
1542
1631
else
0 commit comments