@@ -547,32 +547,35 @@ vacuum(List *relations, VacuumParams *params,
547547}
548548
549549/*
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.
555554 */
556555bool
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 )
558558{
559559 char * relname ;
560+ AclMode mode = 0 ;
560561
561562 Assert ((options & (VACOPT_VACUUM | VACOPT_ANALYZE )) != 0 );
562563
563564 /*
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
573571 */
572+ if (options & VACOPT_VACUUM )
573+ mode |= ACL_VACUUM ;
574+ if (options & VACOPT_ANALYZE )
575+ mode |= ACL_ANALYZE ;
574576 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 )
576579 return true;
577580
578581 relname = NameStr (reltuple -> relname );
@@ -787,10 +790,10 @@ expand_vacuum_rel(VacuumRelation *vrel, int options)
787790 classForm = (Form_pg_class ) GETSTRUCT (tuple );
788791
789792 /*
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 .
792795 */
793- if (vacuum_is_relation_owner (relid , classForm , options ))
796+ if (vacuum_is_permitted_for_relation (relid , classForm , options ))
794797 {
795798 oldcontext = MemoryContextSwitchTo (vac_context );
796799 vacrels = lappend (vacrels , makeVacuumRelation (vrel -> relation ,
@@ -877,7 +880,7 @@ get_all_vacuum_rels(int options)
877880 Oid relid = classForm -> oid ;
878881
879882 /* check permissions of relation */
880- if (!vacuum_is_relation_owner (relid , classForm , options ))
883+ if (!vacuum_is_permitted_for_relation (relid , classForm , options ))
881884 continue ;
882885
883886 /*
@@ -1797,7 +1800,9 @@ vac_truncate_clog(TransactionId frozenXID,
17971800 * be stale.
17981801 *
17991802 * 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.
18011806 *
18021807 * Doing one heap at a time incurs extra overhead, since we need to
18031808 * check that the heap exists again just before we vacuum it. The
@@ -1889,21 +1894,20 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params)
18891894 }
18901895
18911896 /*
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
18931898 * happens also when building the relation list to vacuum for a manual
18941899 * 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.
18981902 */
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 ))
19021906 {
19031907 relation_close (rel , lmode );
19041908 PopActiveSnapshot ();
19051909 CommitTransactionCommand ();
1906- return false;
1910+ return true; /* user might have the ANALYZE privilege */
19071911 }
19081912
19091913 /*
0 commit comments