diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml index 1c21fafb80..47cef987d4 100644 --- a/doc/src/sgml/ref/reindex.sgml +++ b/doc/src/sgml/ref/reindex.sgml @@ -225,10 +225,15 @@ REINDEX [ ( VERBOSE ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } Reindexing a single index or table requires being the owner of that - index or table. Reindexing a database requires being the owner of - the database (note that the owner can therefore rebuild indexes of - tables owned by other users). Of course, superusers can always - reindex anything. + index or table. Reindexing a schema or database requires being the + owner of that schema or database. Note that is therefore sometimes + possible for non-superusers to rebuild indexes of tables owned by + other users. However, as a special exception, when + REINDEX DATABASE, REINDEX SCHEMA + or REINDEX SYSTEM is issued by a non-superuser, + indexes on shared catalogs will be skipped unless the user owns the + catalog (which typically won't be the case). Of course, superusers + can always reindex anything. diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index b9dad9672e..d54c78c352 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -2415,6 +2415,18 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, !IsSystemClass(relid, classtuple)) continue; + /* + * The table can be reindexed if the user is superuser, the table + * owner, or the database/schema owner (but in the latter case, only + * if it's not a shared relation). pg_class_ownercheck includes the + * superuser case, and depending on objectKind we already know that + * the user has permission to run REINDEX on this database or schema + * per the permission checks at the beginning of this routine. + */ + if (classtuple->relisshared && + !pg_class_ownercheck(relid, GetUserId())) + continue; + /* Save the list of relation OIDs in private context */ old = MemoryContextSwitchTo(private_context);