* If not, issue a WARNING log message and return false to let the caller
* decide what to do with this relation. This routine is used to decide if a
* relation can be processed for VACUUM or ANALYZE.
+ *
+ * If missing_ok is true, we silently return false if the relation is
+ * concurrently dropped. Callers without a lock on the relation must specify
+ * missing_ok; all others must hold at least AccessShareLock.
*/
bool
vacuum_is_permitted_for_relation(Oid relid, Form_pg_class reltuple,
- uint32 options)
+ uint32 options, bool missing_ok)
{
char *relname;
+ bool is_missing = false;
Assert((options & (VACOPT_VACUUM | VACOPT_ANALYZE)) != 0);
+ Assert(missing_ok ||
+ CheckRelationOidLockedByMe(relid, AccessShareLock, true));
/*----------
* A role has privileges to vacuum or analyze the relation if any of the
*/
if ((object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) &&
!reltuple->relisshared) ||
- pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) == ACLCHECK_OK)
+ pg_class_aclcheck_ext(relid, GetUserId(), ACL_MAINTAIN,
+ missing_ok ? &is_missing : NULL) == ACLCHECK_OK)
return true;
+ /*
+ * If the relation was concurrently dropped, nothing to do. Note that
+ * this is only reachable when the caller specified missing_ok.
+ */
+ if (is_missing)
+ {
+ Assert(missing_ok);
+ return false;
+ }
+
relname = NameStr(reltuple->relname);
if ((options & VACOPT_VACUUM) != 0)
* Make a returnable VacuumRelation for this rel if the user has the
* required privileges.
*/
- if (vacuum_is_permitted_for_relation(relid, classForm, options))
+ if (vacuum_is_permitted_for_relation(relid, classForm, options, false))
{
oldcontext = MemoryContextSwitchTo(vac_context);
vacrels = lappend(vacrels, makeVacuumRelation(vrel->relation,
continue;
/* check permissions of relation */
- if (!vacuum_is_permitted_for_relation(relid, classForm, options))
+ if (!vacuum_is_permitted_for_relation(relid, classForm, options, true))
continue;
/*
*/
if (!vacuum_is_permitted_for_relation(priv_relid,
rel->rd_rel,
- params.options & ~VACOPT_ANALYZE))
+ params.options & ~VACOPT_ANALYZE,
+ false))
{
relation_close(rel, lmode);
PopActiveSnapshot();