@@ -547,32 +547,35 @@ vacuum(List *relations, VacuumParams *params,
547
547
}
548
548
549
549
/*
550
- * Check if a given relation can be safely vacuumed or analyzed. If the
551
- * user is not the relation owner, issue a WARNING log message and return
552
- * false to let the caller decide what to do with this relation. This
553
- * routine is used to decide if a relation can be processed for VACUUM or
554
- * ANALYZE.
550
+ * Check if the current user has privileges to vacuum or analyze the relation.
551
+ * If not, issue a WARNING log message and return false to let the caller
552
+ * decide what to do with this relation. This routine is used to decide if a
553
+ * relation can be processed for VACUUM or ANALYZE.
555
554
*/
556
555
bool
557
- vacuum_is_relation_owner (Oid relid , Form_pg_class reltuple , bits32 options )
556
+ vacuum_is_permitted_for_relation (Oid relid , Form_pg_class reltuple ,
557
+ bits32 options )
558
558
{
559
559
char * relname ;
560
+ AclMode mode = 0 ;
560
561
561
562
Assert ((options & (VACOPT_VACUUM | VACOPT_ANALYZE )) != 0 );
562
563
563
564
/*
564
- * Check permissions.
565
- *
566
- * We allow the user to vacuum or analyze a table if he is superuser, the
567
- * table owner, or the database owner (but in the latter case, only if
568
- * it's not a shared relation). object_ownercheck includes the
569
- * superuser case.
570
- *
571
- * Note we choose to treat permissions failure as a WARNING and keep
572
- * trying to vacuum or analyze the rest of the DB --- is this appropriate?
565
+ * A role has privileges to vacuum or analyze the relation if any of the
566
+ * following are true:
567
+ * - the role is a superuser
568
+ * - the role owns the relation
569
+ * - the role owns the current database and the relation is not shared
570
+ * - the role has been granted privileges to vacuum/analyze the relation
573
571
*/
572
+ if (options & VACOPT_VACUUM )
573
+ mode |= ACL_VACUUM ;
574
+ if (options & VACOPT_ANALYZE )
575
+ mode |= ACL_ANALYZE ;
574
576
if (object_ownercheck (RelationRelationId , relid , GetUserId ()) ||
575
- (object_ownercheck (DatabaseRelationId , MyDatabaseId , GetUserId ()) && !reltuple -> relisshared ))
577
+ (object_ownercheck (DatabaseRelationId , MyDatabaseId , GetUserId ()) && !reltuple -> relisshared ) ||
578
+ pg_class_aclcheck (relid , GetUserId (), mode ) == ACLCHECK_OK )
576
579
return true;
577
580
578
581
relname = NameStr (reltuple -> relname );
@@ -787,10 +790,10 @@ expand_vacuum_rel(VacuumRelation *vrel, int options)
787
790
classForm = (Form_pg_class ) GETSTRUCT (tuple );
788
791
789
792
/*
790
- * Make a returnable VacuumRelation for this rel if user is a proper
791
- * owner .
793
+ * Make a returnable VacuumRelation for this rel if the user has the
794
+ * required privileges .
792
795
*/
793
- if (vacuum_is_relation_owner (relid , classForm , options ))
796
+ if (vacuum_is_permitted_for_relation (relid , classForm , options ))
794
797
{
795
798
oldcontext = MemoryContextSwitchTo (vac_context );
796
799
vacrels = lappend (vacrels , makeVacuumRelation (vrel -> relation ,
@@ -877,7 +880,7 @@ get_all_vacuum_rels(int options)
877
880
Oid relid = classForm -> oid ;
878
881
879
882
/* check permissions of relation */
880
- if (!vacuum_is_relation_owner (relid , classForm , options ))
883
+ if (!vacuum_is_permitted_for_relation (relid , classForm , options ))
881
884
continue ;
882
885
883
886
/*
@@ -1797,7 +1800,9 @@ vac_truncate_clog(TransactionId frozenXID,
1797
1800
* be stale.
1798
1801
*
1799
1802
* Returns true if it's okay to proceed with a requested ANALYZE
1800
- * operation on this table.
1803
+ * operation on this table. Note that if vacuuming fails because the user
1804
+ * does not have the required privileges, this function returns true since
1805
+ * the user might have been granted privileges to ANALYZE the relation.
1801
1806
*
1802
1807
* Doing one heap at a time incurs extra overhead, since we need to
1803
1808
* check that the heap exists again just before we vacuum it. The
@@ -1889,21 +1894,20 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
1889
1894
}
1890
1895
1891
1896
/*
1892
- * Check if relation needs to be skipped based on ownership . This check
1897
+ * Check if relation needs to be skipped based on privileges . This check
1893
1898
* happens also when building the relation list to vacuum for a manual
1894
1899
* operation, and needs to be done additionally here as VACUUM could
1895
- * happen across multiple transactions where relation ownership could have
1896
- * changed in-between. Make sure to only generate logs for VACUUM in this
1897
- * case.
1900
+ * happen across multiple transactions where privileges could have changed
1901
+ * in-between. Make sure to only generate logs for VACUUM in this case.
1898
1902
*/
1899
- if (!vacuum_is_relation_owner (RelationGetRelid (rel ),
1900
- rel -> rd_rel ,
1901
- params -> options & VACOPT_VACUUM ))
1903
+ if (!vacuum_is_permitted_for_relation (RelationGetRelid (rel ),
1904
+ rel -> rd_rel ,
1905
+ VACOPT_VACUUM ))
1902
1906
{
1903
1907
relation_close (rel , lmode );
1904
1908
PopActiveSnapshot ();
1905
1909
CommitTransactionCommand ();
1906
- return false;
1910
+ return true; /* user might have the ANALYZE privilege */
1907
1911
}
1908
1912
1909
1913
/*
0 commit comments