TRUNCATE , REFERENCES , TRIGGER ,
CREATE , CONNECT , TEMPORARY ,
EXECUTE , USAGE , SET ,
- ALTER SYSTEM , VACUUM , and
- ANALYZE .
+ ALTER SYSTEM , and MAINTAIN .
The privileges applicable to a particular
object vary depending on the object's type (table, function, etc.).
More detail about the meanings of these privileges appears below.
- VACUUM
+ MAINTAIN
- Allows VACUUM on a relation.
-
-
-
-
-
- ANALYZE
-
- Allows ANALYZE on a relation.
+ Allows VACUUM , ANALYZE ,
+ CLUSTER , REFRESH MATERIALIZED VIEW ,
+ REINDEX , and LOCK TABLE on a
+ relation.
PARAMETER
|
- VACUUM
- v
- TABLE
-
- |
- ANALYZE
- z
+ MAINTAIN
+ m
TABLE
|
TABLE (and table-like objects)
- arwdDxtvz
+ arwdDxtm
none
\dp
would show:
=> \dp mytable
- Access privileges
- Schema | Name | Type | Access privileges | Column privileges | Policies
---------+---------+-------+------------------------- +-----------------------+----------
- public | mytable | table | miriam=arwdDxtvz /miriam+| col1: +|
- | | | =r/miriam +| miriam_rw=rw/miriam |
- | | | admin=arw/miriam | |
+ Access privileges
+ Schema | Name | Type | Access privileges | Column privileges | Policies
+--------+---------+-------+------------------------+-----------------------+----------
+ public | mytable | table | miriam=arwdDxtm /miriam+| col1: +|
+ | | | =r/miriam +| miriam_rw=rw/miriam |
+ | | | admin=arw/miriam | |
(1 row)
are SELECT , INSERT ,
UPDATE , DELETE ,
TRUNCATE , REFERENCES ,
- TRIGGER , VACUUM and
- ANALYZE .
+ TRIGGER , and MAINTAIN .
where abbreviated_grant_or_revoke is one of:
-GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | VACUUM | ANALYZE }
+GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
[, ...] | ALL [ PRIVILEGES ] }
ON TABLES
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]
REVOKE [ GRANT OPTION FOR ]
- { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | VACUUM | ANALYZE }
+ { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
[, ...] | ALL [ PRIVILEGES ] }
ON TABLES
FROM { [ GROUP ] role_name | PUBLIC } [, ...]
Notes
- To analyze a table, one must ordinarily have the ANALYZE
+ To analyze a table, one must ordinarily have the MAINTAIN
privilege on the table or be the table's owner, a superuser, or a role with
privileges of the
- pg_analyze_all_tables
- role.
- However, database owners are allowed to
+ pg_maintain
+ role. However, database owners are allowed to
analyze all tables in their databases, except shared catalogs.
(The restriction for shared catalogs means that a true database-wide
ANALYZE can only be performed by superusers and roles
- with privileges of pg_analyze_all_tables .)
+ with privileges of pg_maintain .)
ANALYZE will skip over any tables that the calling user
does not have permission to analyze.
CLUSTER without any parameter reclusters all the
previously-clustered tables in the current database that the calling user
- owns, or all such tables if called by a superuser. This
- form of CLUSTER cannot be executed inside a transaction
- block.
+ owns or has the MAINTAIN privilege for, or all such tables
+ if called by a superuser or a role with privileges of the
+ pg_maintain
+ role. This form of CLUSTER cannot be
+ executed inside a transaction block.
-GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | VACUUM | ANALYZE }
+GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
USAGE
SET
ALTER SYSTEM
- VACUUM
- ANALYZE
+ MAINTAIN
Specific types of privileges, as defined in .
Notes
- LOCK TABLE ... IN ACCESS SHARE MODE requires SELECT
- privileges on the target table. LOCK TABLE ... IN ROW EXCLUSIVE
- MODE requires INSERT , UPDATE , DELETE ,
- or TRUNCATE privileges on the target table. All other forms of
- LOCK require table-level UPDATE , DELETE ,
+ To lock a table, one must ordinarily have the MAINTAIN
+ privilege on the table or be the table's owner, a superuser, or a role
+ with privileges of the
+ pg_maintain
+ role. LOCK TABLE ... IN ACCESS SHARE MODE is allowed
+ with SELECT privileges on the target
+ table. LOCK TABLE ... IN ROW EXCLUSIVE MODE is allowed
+ with INSERT , UPDATE , DELETE ,
+ or TRUNCATE privileges on the target table. All other
+ forms of LOCK are allowed with
+ table-level UPDATE , DELETE ,
or TRUNCATE privileges.
REFRESH MATERIALIZED VIEW completely replaces the
contents of a materialized view. To execute this command you must be the
- owner of the materialized view. The old contents are discarded. If
+ owner of the materialized view, have privileges of the
+ pg_maintain
+ role, or have the MAINTAIN
+ privilege on the materialized view. The old contents are discarded. If
WITH DATA is specified (or defaults) the backing query
is executed to provide the new data, and the materialized view is left in a
scannable state. If WITH NO DATA is specified no new
Reindexing a single index or table requires being the owner of that
- index or table. Reindexing a schema or database requires being the
- owner of that schema or database. Note specifically that it's thus
+ index or table, having privileges of the
+ pg_maintain
+ role, or having the MAINTAIN privilege on the
+ table. Reindexing a schema or database requires being the
+ owner of that schema or database or having privileges of the
+ pg_maintain role. Note specifically that it's thus
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.
+ catalog (which typically won't be the case), has privileges of the
+ pg_maintain role, or has the MAINTAIN
+ privilege on the catalog. Of course, superusers can always reindex anything.
REVOKE [ GRANT OPTION FOR ]
- { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | VACUUM | ANALYZE }
+ { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | MAINTAIN }
[, ...] | ALL [ PRIVILEGES ] }
ON { [ TABLE ] table_name [, ...]
| ALL TABLES IN SCHEMA schema_name [, ...] }
Notes
- To vacuum a table, one must ordinarily have the VACUUM
+ To vacuum a table, one must ordinarily have the MAINTAIN
privilege on the table or be the table's owner, a superuser, or a role with
privileges of the
- pg_vacuum_all_tables
- role.
- However, database owners are allowed to
+ pg_maintain
+ role. However, database owners are allowed to
vacuum all tables in their databases, except shared catalogs.
(The restriction for shared catalogs means that a true database-wide
VACUUM can only be performed by superusers and roles
- with privileges of pg_vacuum_all_tables .)
+ with privileges of pg_maintain .)
VACUUM will skip over any tables that the calling user
does not have permission to vacuum.
command.
|
- pg_vacuum_all_tables
- Allow executing the
- VACUUM command on
- all tables.
-
- |
- pg_analyze_all_tables
- Allow executing the
- ANALYZE command on
- all tables.
+ pg_maintain
+ Allow executing
+ VACUUM ,
+ ANALYZE ,
+ CLUSTER ,
+ REFRESH MATERIALIZED VIEW ,
+ REINDEX ,
+ and LOCK TABLE on all
+ relations.
return ACL_SET;
if (strcmp(privname, "alter system") == 0)
return ACL_ALTER_SYSTEM;
- if (strcmp(privname, "vacuum") == 0)
- return ACL_VACUUM;
- if (strcmp(privname, "analyze") == 0)
- return ACL_ANALYZE;
+ if (strcmp(privname, "maintain") == 0)
+ return ACL_MAINTAIN;
if (strcmp(privname, "rule") == 0)
return 0; /* ignore old RULE privileges */
ereport(ERROR,
return "SET";
case ACL_ALTER_SYSTEM:
return "ALTER SYSTEM";
- case ACL_VACUUM:
- return "VACUUM";
- case ACL_ANALYZE:
- return "ANALYZE";
+ case ACL_MAINTAIN:
+ return "MAINTAIN";
default:
elog(ERROR, "unrecognized privilege: %d", (int) privilege);
}
result |= (mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE));
/*
- * Check if ACL_VACUUM is being checked and, if so, and not already set as
+ * Check if ACL_MAINTAIN is being checked and, if so, and not already set as
* part of the result, then check if the user is a member of the
- * pg_vacuum_all_tables role, which allows VACUUM on all relations.
+ * pg_maintain role, which allows VACUUM, ANALYZE, CLUSTER, REFRESH
+ * MATERIALIZED VIEW, and REINDEX on all relations.
*/
- if (mask & ACL_VACUUM &&
- !(result & ACL_VACUUM) &&
- has_privs_of_role(roleid, ROLE_PG_VACUUM_ALL_TABLES))
- result |= ACL_VACUUM;
-
- /*
- * Check if ACL_ANALYZE is being checked and, if so, and not already set as
- * part of the result, then check if the user is a member of the
- * pg_analyze_all_tables role, which allows ANALYZE on all relations.
- */
- if (mask & ACL_ANALYZE &&
- !(result & ACL_ANALYZE) &&
- has_privs_of_role(roleid, ROLE_PG_ANALYZE_ALL_TABLES))
- result |= ACL_ANALYZE;
+ if (mask & ACL_MAINTAIN &&
+ !(result & ACL_MAINTAIN) &&
+ has_privs_of_role(roleid, ROLE_PG_MAINTAIN))
+ result |= ACL_MAINTAIN;
return result;
}
*/
if (!vacuum_is_permitted_for_relation(RelationGetRelid(onerel),
onerel->rd_rel,
- VACOPT_ANALYZE))
+ params->options & VACOPT_ANALYZE))
{
relation_close(onerel, ShareUpdateExclusiveLock);
return;
tableOid = RangeVarGetRelidExtended(stmt->relation,
AccessExclusiveLock,
0,
- RangeVarCallbackOwnsTable, NULL);
+ RangeVarCallbackMaintainsTable,
+ NULL);
rel = table_open(tableOid, NoLock);
/*
*/
if (recheck)
{
- /* Check that the user still owns the relation */
- if (!object_ownercheck(RelationRelationId, tableOid, save_userid))
+ /* Check that the user still has privileges for the relation */
+ if (!object_ownercheck(RelationRelationId, tableOid, save_userid) &&
+ pg_class_aclcheck(tableOid, save_userid, ACL_MAINTAIN) != ACLCHECK_OK)
{
relation_close(OldHeap, AccessExclusiveLock);
goto out;
/*
- * Get a list of tables that the current user owns and
+ * Get a list of tables that the current user has privileges on and
* have indisclustered set. Return the list in a List * of RelToCluster
* (stored in the specified memory context), each one giving the tableOid
* and the indexOid on which the table is already clustered.
List *rtcs = NIL;
/*
- * Get all indexes that have indisclustered set and are owned by
- * appropriate use r.
+ * Get all indexes that have indisclustered set and that the current user
+ * has the appropriate privileges fo r.
*/
indRelation = table_open(IndexRelationId, AccessShareLock);
ScanKeyInit(&entry,
index = (Form_pg_index) GETSTRUCT(indexTuple);
- if (!object_ownercheck(RelationRelationId, index->indrelid, GetUserId()))
+ if (!object_ownercheck(RelationRelationId, index->indrelid, GetUserId()) &&
+ pg_class_aclcheck(index->indrelid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK)
continue;
/* Use a permanent memory context for the result list */
/* Silently skip partitions which the user has no access to. */
if (!object_ownercheck(RelationRelationId, relid, GetUserId()) &&
+ pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK &&
(!object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) ||
IsSharedRelation(relid)))
continue;
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/pg_am.h"
+#include "catalog/pg_authid.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_database.h"
#include "catalog/pg_inherits.h"
char relkind;
struct ReindexIndexCallbackState *state = arg;
LOCKMODE table_lockmode;
+ Oid table_oid;
/*
* Lock level here should match table lock in reindex_index() for
errmsg("\"%s\" is not an index", relation->relname)));
/* Check permissions */
- if (!object_ownercheck(RelationRelationId, relId, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_INDEX, relation->relname);
+ table_oid = IndexGetRelation(relId, true);
+ if (!object_ownercheck(RelationRelationId, relId, GetUserId()) &&
+ OidIsValid(table_oid) &&
+ pg_class_aclcheck(table_oid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK)
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_INDEX,
+ relation->relname);
/* Lock heap before index to avoid deadlock. */
if (relId != oldRelId)
{
- Oid table_oid = IndexGetRelation(relId, true);
-
/*
* If the OID isn't valid, it means the index was concurrently
* dropped, which is not a problem for us; just return normally.
(params->options & REINDEXOPT_CONCURRENTLY) != 0 ?
ShareUpdateExclusiveLock : ShareLock,
0,
- RangeVarCallbackOw nsTable, NULL);
+ RangeVarCallbackMaintai nsTable, NULL);
if (get_rel_relkind(heapOid) == RELKIND_PARTITIONED_TABLE)
ReindexPartitions(heapOid, params, isTopLevel);
{
objectOid = get_namespace_oid(objectName, false);
- if (!object_ownercheck(NamespaceRelationId, objectOid, GetUserId()))
+ if (!object_ownercheck(NamespaceRelationId, objectOid, GetUserId()) &&
+ !has_privs_of_role(GetUserId(), ROLE_PG_MAINTAIN))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA,
objectName);
}
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("can only reindex the currently open database")));
- if (!object_ownercheck(DatabaseRelationId, objectOid, GetUserId()))
+ if (!object_ownercheck(DatabaseRelationId, objectOid, GetUserId()) &&
+ !has_privs_of_role(GetUserId(), ROLE_PG_MAINTAIN))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_DATABASE,
get_database_name(objectOid));
}
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). object_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.
+ * The table can be reindexed if the user has been granted MAINTAIN on
+ * the table or the user is a superuser, the table owner, or the
+ * database/schema owner (but in the latter case, only if it's not a
+ * shared relation). object_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 &&
- !object_ownercheck(RelationRelationId, relid, GetUserId()))
+ !object_ownercheck(RelationRelationId, relid, GetUserId()) &&
+ pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK)
continue;
/*
else
aclmask = ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE;
+ /* MAINTAIN privilege allows all lock modes */
+ aclmask |= ACL_MAINTAIN;
+
aclresult = pg_class_aclcheck(reloid, userid, aclmask);
return aclresult;
*/
matviewOid = RangeVarGetRelidExtended(stmt->relation,
lockmode, 0,
- RangeVarCallbackOwnsTable, NULL);
+ RangeVarCallbackMaintainsTable,
+ NULL);
matviewRel = table_open(matviewOid, NoLock);
relowner = matviewRel->rd_rel->relowner;
* This is intended as a callback for RangeVarGetRelidExtended(). It allows
* the relation to be locked only if (1) it's a plain or partitioned table,
* materialized view, or TOAST table and (2) the current user is the owner (or
- * the superuser). This meets the permission-checking needs of CLUSTER,
- * REINDEX TABLE, and REFRESH MATERIALIZED VIEW; we expose it here so that it
- * can be used by all.
+ * the superuser) or has been granted MAINTAIN. This meets the
+ * permission-checking needs of CLUSTER, REINDEX TABLE, and REFRESH
+ * MATERIALIZED VIEW; we expose it here so that it can be used by all.
*/
void
-RangeVarCallbackOw nsTable(const RangeVar *relation,
- Oid relId, Oid oldRelId, void *arg)
+RangeVarCallbackMaintai nsTable(const RangeVar *relation,
+ Oid relId, Oid oldRelId, void *arg)
{
char relkind;
errmsg("\"%s\" is not a table or materialized view", relation->relname)));
/* Check permissions */
- if (!object_ownercheck(RelationRelationId, relId, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(relId)), relation->relname);
+ if (!object_ownercheck(RelationRelationId, relId, GetUserId()) &&
+ pg_class_aclcheck(relId, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK)
+ aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLE,
+ relation->relname);
}
/*
bits32 options)
{
char *relname;
- AclMode mode = 0;
Assert((options & (VACOPT_VACUUM | VACOPT_ANALYZE)) != 0);
* - the role is a superuser
* - the role owns the relation
* - the role owns the current database and the relation is not shared
- * - the role has been granted privileges to vacuum/analyze the relation
+ * - the role has been granted the MAINTAIN privilege on the relation
*/
- if (options & VACOPT_VACUUM)
- mode |= ACL_VACUUM;
- if (options & VACOPT_ANALYZE)
- mode |= ACL_ANALYZE;
if (object_ownercheck(RelationRelationId, relid, GetUserId()) ||
(object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) && !reltuple->relisshared) ||
- pg_class_aclcheck(relid, GetUserId(), mode ) == ACLCHECK_OK)
+ pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN ) == ACLCHECK_OK)
return true;
relname = NameStr(reltuple->relname);
* be stale.
*
* Returns true if it's okay to proceed with a requested ANALYZE
- * operation on this table. Note that if vacuuming fails because the user
- * does not have the required privileges, this function returns true since
- * the user might have been granted privileges to ANALYZE the relation.
+ * operation on this table.
*
* Doing one heap at a time incurs extra overhead, since we need to
* check that the heap exists again just before we vacuum it. The
*/
if (!vacuum_is_permitted_for_relation(RelationGetRelid(rel),
rel->rd_rel,
- VACOPT_VACUUM))
+ params->options & VACOPT_VACUUM))
{
relation_close(rel, lmode);
PopActiveSnapshot();
CommitTransactionCommand();
- return true; /* user might have the ANALYZE privilege */
+ return false;
}
/*
n->cols = NIL;
$$ = n;
}
- | analyze_keyword
- {
- AccessPriv *n = makeNode(AccessPriv);
- n->priv_name = pstrdup("analyze");
- n->cols = NIL;
- $$ = n;
- }
| ColId opt_column_list
{
AccessPriv *n = makeNode(AccessPriv);
case ACL_ALTER_SYSTEM_CHR:
read = ACL_ALTER_SYSTEM;
break;
- case ACL_VACUUM_CHR:
- read = ACL_VACUUM;
- break;
- case ACL_ANALYZE_CHR:
- read = ACL_ANALYZE;
+ case ACL_MAINTAIN_CHR:
+ read = ACL_MAINTAIN;
break;
case 'R': /* ignore old RULE privileges */
read = 0;
{"CONNECT", ACL_CONNECT},
{"SET", ACL_SET},
{"ALTER SYSTEM", ACL_ALTER_SYSTEM},
- {"VACUUM", ACL_VACUUM},
- {"ANALYZE", ACL_ANALYZE},
+ {"MAINTAIN", ACL_MAINTAIN},
{"RULE", 0}, /* ignore old RULE privileges */
{NULL, 0}
};
return "SET";
case ACL_ALTER_SYSTEM:
return "ALTER SYSTEM";
- case ACL_VACUUM:
- return "VACUUM";
- case ACL_ANALYZE:
- return "ANALYZE";
+ case ACL_MAINTAIN:
+ return "MAINTAIN";
default:
elog(ERROR, "unrecognized aclright: %d", aclright);
return NULL;
{"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
{"TRIGGER", ACL_TRIGGER},
{"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
- {"VACUUM", ACL_VACUUM},
- {"VACUUM WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_VACUUM)},
- {"ANALYZE", ACL_ANALYZE},
- {"ANALYZE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_ANALYZE)},
+ {"MAINTAIN", ACL_MAINTAIN},
+ {"MAINTAIN WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_MAINTAIN)},
{"RULE", 0}, /* ignore old RULE privileges */
{"RULE WITH GRANT OPTION", 0},
{NULL, 0}
CONVERT_PRIV('d', "DELETE");
CONVERT_PRIV('t', "TRIGGER");
CONVERT_PRIV('D', "TRUNCATE");
- CONVERT_PRIV('v', "VACUUM");
- CONVERT_PRIV('z', "ANALYZE");
+ CONVERT_PRIV('m', "MAINTAIN");
}
}
\QREVOKE ALL ON TABLES FROM regress_dump_test_role;\E\n
\QALTER DEFAULT PRIVILEGES \E
\QFOR ROLE regress_dump_test_role \E
- \QGRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,VACUUM,ANALYZE ,UPDATE ON TABLES TO regress_dump_test_role;\E
+ \QGRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,MAINTAIN ,UPDATE ON TABLES TO regress_dump_test_role;\E
/xm,
like => { %full_runs, section_post_data => 1, },
unlike => { no_privs => 1, },
#define Privilege_options_of_grant_and_revoke \
"SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER", \
"CREATE", "CONNECT", "TEMPORARY", "EXECUTE", "USAGE", "SET", "ALTER SYSTEM", \
-"VACUUM", "ANALYZE ", "ALL"
+"MAINTAIN ", "ALL"
/*
* These object types were introduced later than our support cutoff of
if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES"))
COMPLETE_WITH("SELECT", "INSERT", "UPDATE",
"DELETE", "TRUNCATE", "REFERENCES", "TRIGGER",
- "CREATE", "EXECUTE", "USAGE", "VACUUM", "ANALYZE",
- "ALL");
+ "CREATE", "EXECUTE", "USAGE", "MAINTAIN", "ALL");
else if (TailMatches("GRANT"))
COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles,
Privilege_options_of_grant_and_revoke);
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 20221212 1
+#define CATALOG_VERSION_NO 20221213 1
#endif
rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
rolpassword => '_null_', rolvaliduntil => '_null_' },
-{ oid => '4549', oid_symbol => 'ROLE_PG_VACUUM_ALL_TABLES',
- rolname => 'pg_vacuum_all_tables', rolsuper => 'f', rolinherit => 't',
- rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
- rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
- rolpassword => '_null_', rolvaliduntil => '_null_' },
-{ oid => '4550', oid_symbol => 'ROLE_PG_ANALYZE_ALL_TABLES',
- rolname => 'pg_analyze_all_tables', rolsuper => 'f', rolinherit => 't',
+{ oid => '4549', oid_symbol => 'ROLE_PG_MAINTAIN',
+ rolname => 'pg_maintain', rolsuper => 'f', rolinherit => 't',
rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
rolpassword => '_null_', rolvaliduntil => '_null_' },
SubTransactionId mySubid,
SubTransactionId parentSubid);
-extern void RangeVarCallbackOwnsTable(const RangeVar *relation,
- Oid relId, Oid oldRelId, void *arg);
+extern void RangeVarCallbackMaintainsTable(const RangeVar *relation,
+ Oid relId, Oid oldRelId,
+ void *arg);
extern void RangeVarCallbackOwnsRelation(const RangeVar *relation,
Oid relId, Oid oldRelId, void *arg);
#define ACL_CONNECT (1<<11) /* for databases */
#define ACL_SET (1<<12) /* for configuration parameters */
#define ACL_ALTER_SYSTEM (1<<13) /* for configuration parameters */
-#define ACL_VACUUM (1<<14) /* for relations */
-#define ACL_ANALYZE (1<<15) /* for relations */
-#define N_ACL_RIGHTS 16 /* 1 plus the last 1<
+#define ACL_MAINTAIN (1<<14) /* for relations */
+#define N_ACL_RIGHTS 15 /* 1 plus the last 1<
#define ACL_NO_RIGHTS 0
/* Currently, SELECT ... FOR [KEY] UPDATE/SHARE requires UPDATE privileges */
#define ACL_SELECT_FOR_UPDATE ACL_UPDATE
#define ACL_CONNECT_CHR 'c'
#define ACL_SET_CHR 's'
#define ACL_ALTER_SYSTEM_CHR 'A'
-#define ACL_VACUUM_CHR 'v'
-#define ACL_ANALYZE_CHR 'z'
+#define ACL_MAINTAIN_CHR 'm'
/* string holding all privilege code chars, in order by bitmask position */
-#define ACL_ALL_RIGHTS_STR "arwdDxtXUCTcsAvz "
+#define ACL_ALL_RIGHTS_STR "arwdDxtXUCTcsAm "
/*
* Bitmasks defining "all rights" for each supported object type
*/
#define ACL_ALL_RIGHTS_COLUMN (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_REFERENCES)
-#define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER|ACL_VACUUM|ACL_ANALYZE )
+#define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER|ACL_MAINTAIN )
#define ACL_ALL_RIGHTS_SEQUENCE (ACL_USAGE|ACL_SELECT|ACL_UPDATE)
#define ACL_ALL_RIGHTS_DATABASE (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
#define ACL_ALL_RIGHTS_FDW (ACL_USAGE)
REVOKE SELECT ON deptest FROM GROUP regress_dep_group;
DROP GROUP regress_dep_group;
-- can't drop the user if we revoke the privileges partially
-REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, VACUUM, ANALYZE ON deptest FROM regress_dep_user;
+REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, MAINTAIN ON deptest FROM regress_dep_user;
DROP USER regress_dep_user;
ERROR: role "regress_dep_user" cannot be dropped because some objects depend on it
DETAIL: privileges for table deptest
GRANT ALL ON deptest1 TO regress_dep_user2;
RESET SESSION AUTHORIZATION;
\z deptest1
- Access privileges
- Schema | Name | Type | Access privileges | Column privileges | Policies
---------+----------+-------+-------------------------------------------------------- +-------------------+----------
- public | deptest1 | table | regress_dep_user0=arwdDxtvz/regress_dep_user0 +| |
- | | | regress_dep_user1=a*r*w*d*D*x*t*v*z */regress_dep_user0+| |
- | | | regress_dep_user2=arwdDxtvz/regress_dep_user1 | |
+ Access privileges
+ Schema | Name | Type | Access privileges | Column privileges | Policies
+--------+----------+-------+------------------------------------------------------+-------------------+----------
+ public | deptest1 | table | regress_dep_user0=arwdDxtm/regress_dep_user0 +| |
+ | | | regress_dep_user1=a*r*w*d*D*x*t*m */regress_dep_user0+| |
+ | | | regress_dep_user2=arwdDxtm/regress_dep_user1 | |
(1 row)
DROP OWNED BY regress_dep_user1;
-- all grants revoked
\z deptest1
Access privileges
- Schema | Name | Type | Access privileges | Column privileges | Policies
---------+----------+-------+----------------------------------------------- +-------------------+----------
- public | deptest1 | table | regress_dep_user0=arwdDxtvz /regress_dep_user0 | |
+ Schema | Name | Type | Access privileges | Column privileges | Policies
+--------+----------+-------+----------------------------------------------+-------------------+----------
+ public | deptest1 | table | regress_dep_user0=arwdDxtm /regress_dep_user0 | |
(1 row)
-- table was dropped
set session role regress_priv_user4;
grant select on dep_priv_test to regress_priv_user5;
\dp dep_priv_test
- Access privileges
- Schema | Name | Type | Access privileges | Column privileges | Policies
---------+---------------+-------+------------------------------------------------- +-------------------+----------
- public | dep_priv_test | table | regress_priv_user1=arwdDxtvz /regress_priv_user1+| |
- | | | regress_priv_user2=r*/regress_priv_user1 +| |
- | | | regress_priv_user3=r*/regress_priv_user1 +| |
- | | | regress_priv_user4=r*/regress_priv_user2 +| |
- | | | regress_priv_user4=r*/regress_priv_user3 +| |
- | | | regress_priv_user5=r/regress_priv_user4 | |
+ Access privileges
+ Schema | Name | Type | Access privileges | Column privileges | Policies
+--------+---------------+-------+------------------------------------------------+-------------------+----------
+ public | dep_priv_test | table | regress_priv_user1=arwdDxtm /regress_priv_user1+| |
+ | | | regress_priv_user2=r*/regress_priv_user1 +| |
+ | | | regress_priv_user3=r*/regress_priv_user1 +| |
+ | | | regress_priv_user4=r*/regress_priv_user2 +| |
+ | | | regress_priv_user4=r*/regress_priv_user3 +| |
+ | | | regress_priv_user5=r/regress_priv_user4 | |
(1 row)
set session role regress_priv_user2;
revoke select on dep_priv_test from regress_priv_user4 cascade;
\dp dep_priv_test
- Access privileges
- Schema | Name | Type | Access privileges | Column privileges | Policies
---------+---------------+-------+------------------------------------------------- +-------------------+----------
- public | dep_priv_test | table | regress_priv_user1=arwdDxtvz /regress_priv_user1+| |
- | | | regress_priv_user2=r*/regress_priv_user1 +| |
- | | | regress_priv_user3=r*/regress_priv_user1 +| |
- | | | regress_priv_user4=r*/regress_priv_user3 +| |
- | | | regress_priv_user5=r/regress_priv_user4 | |
+ Access privileges
+ Schema | Name | Type | Access privileges | Column privileges | Policies
+--------+---------------+-------+------------------------------------------------+-------------------+----------
+ public | dep_priv_test | table | regress_priv_user1=arwdDxtm /regress_priv_user1+| |
+ | | | regress_priv_user2=r*/regress_priv_user1 +| |
+ | | | regress_priv_user3=r*/regress_priv_user1 +| |
+ | | | regress_priv_user4=r*/regress_priv_user3 +| |
+ | | | regress_priv_user5=r/regress_priv_user4 | |
(1 row)
set session role regress_priv_user3;
revoke select on dep_priv_test from regress_priv_user4 cascade;
\dp dep_priv_test
- Access privileges
- Schema | Name | Type | Access privileges | Column privileges | Policies
---------+---------------+-------+------------------------------------------------- +-------------------+----------
- public | dep_priv_test | table | regress_priv_user1=arwdDxtvz /regress_priv_user1+| |
- | | | regress_priv_user2=r*/regress_priv_user1 +| |
- | | | regress_priv_user3=r*/regress_priv_user1 | |
+ Access privileges
+ Schema | Name | Type | Access privileges | Column privileges | Policies
+--------+---------------+-------+------------------------------------------------+-------------------+----------
+ public | dep_priv_test | table | regress_priv_user1=arwdDxtm /regress_priv_user1+| |
+ | | | regress_priv_user2=r*/regress_priv_user1 +| |
+ | | | regress_priv_user3=r*/regress_priv_user1 | |
(1 row)
set session role regress_priv_user1;
DROP ROLE regress_roleoption_protagonist;
DROP ROLE regress_roleoption_donor;
DROP ROLE regress_roleoption_recipient;
--- VACUUM and ANALYZE
-CREATE ROLE regress_no_priv;
-CREATE ROLE regress_only_vacuum;
-CREATE ROLE regress_only_analyze;
-CREATE ROLE regress_both;
-CREATE ROLE regress_only_vacuum_all IN ROLE pg_vacuum_all_tables;
-CREATE ROLE regress_only_analyze_all IN ROLE pg_analyze_all_tables;
-CREATE ROLE regress_both_all IN ROLE pg_vacuum_all_tables, pg_analyze_all_tables;
-CREATE TABLE vacanalyze_test (a INT);
-GRANT VACUUM ON vacanalyze_test TO regress_only_vacuum, regress_both;
-GRANT ANALYZE ON vacanalyze_test TO regress_only_analyze, regress_both;
-SET ROLE regress_no_priv;
-VACUUM vacanalyze_test;
-WARNING: permission denied to vacuum "vacanalyze_test", skipping it
-ANALYZE vacanalyze_test;
-WARNING: permission denied to analyze "vacanalyze_test", skipping it
-VACUUM (ANALYZE) vacanalyze_test;
-WARNING: permission denied to vacuum "vacanalyze_test", skipping it
-RESET ROLE;
-SET ROLE regress_only_vacuum;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-WARNING: permission denied to analyze "vacanalyze_test", skipping it
-VACUUM (ANALYZE) vacanalyze_test;
-WARNING: permission denied to analyze "vacanalyze_test", skipping it
-RESET ROLE;
-SET ROLE regress_only_analyze;
-VACUUM vacanalyze_test;
-WARNING: permission denied to vacuum "vacanalyze_test", skipping it
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
-WARNING: permission denied to vacuum "vacanalyze_test", skipping it
-RESET ROLE;
-SET ROLE regress_both;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
-RESET ROLE;
-SET ROLE regress_only_vacuum_all;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-WARNING: permission denied to analyze "vacanalyze_test", skipping it
-VACUUM (ANALYZE) vacanalyze_test;
-WARNING: permission denied to analyze "vacanalyze_test", skipping it
+-- MAINTAIN
+CREATE ROLE regress_no_maintain;
+CREATE ROLE regress_maintain;
+CREATE ROLE regress_maintain_all IN ROLE pg_maintain;
+CREATE TABLE maintain_test (a INT);
+CREATE INDEX ON maintain_test (a);
+GRANT MAINTAIN ON maintain_test TO regress_maintain;
+CREATE MATERIALIZED VIEW refresh_test AS SELECT 1;
+GRANT MAINTAIN ON refresh_test TO regress_maintain;
+CREATE SCHEMA reindex_test;
+-- negative tests; should fail
+SET ROLE regress_no_maintain;
+VACUUM maintain_test;
+WARNING: permission denied to vacuum "maintain_test", skipping it
+ANALYZE maintain_test;
+WARNING: permission denied to analyze "maintain_test", skipping it
+VACUUM (ANALYZE) maintain_test;
+WARNING: permission denied to vacuum "maintain_test", skipping it
+CLUSTER maintain_test USING maintain_test_a_idx;
+ERROR: must be owner of table maintain_test
+REFRESH MATERIALIZED VIEW refresh_test;
+ERROR: must be owner of table refresh_test
+REINDEX TABLE maintain_test;
+ERROR: must be owner of table maintain_test
+REINDEX INDEX maintain_test_a_idx;
+ERROR: must be owner of index maintain_test_a_idx
+REINDEX SCHEMA reindex_test;
+ERROR: must be owner of schema reindex_test
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS SHARE MODE;
+ERROR: permission denied for table maintain_test
+COMMIT;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS EXCLUSIVE MODE;
+ERROR: permission denied for table maintain_test
+COMMIT;
RESET ROLE;
-SET ROLE regress_only_analyze_all;
-VACUUM vacanalyze_test;
-WARNING: permission denied to vacuum "vacanalyze_test", skipping it
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
-WARNING: permission denied to vacuum "vacanalyze_test", skipping it
+SET ROLE regress_maintain;
+VACUUM maintain_test;
+ANALYZE maintain_test;
+VACUUM (ANALYZE) maintain_test;
+CLUSTER maintain_test USING maintain_test_a_idx;
+REFRESH MATERIALIZED VIEW refresh_test;
+REINDEX TABLE maintain_test;
+REINDEX INDEX maintain_test_a_idx;
+REINDEX SCHEMA reindex_test;
+ERROR: must be owner of schema reindex_test
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS SHARE MODE;
+COMMIT;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS EXCLUSIVE MODE;
+COMMIT;
RESET ROLE;
-SET ROLE regress_both_all;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
+SET ROLE regress_maintain_all;
+VACUUM maintain_test;
+ANALYZE maintain_test;
+VACUUM (ANALYZE) maintain_test;
+CLUSTER maintain_test USING maintain_test_a_idx;
+REFRESH MATERIALIZED VIEW refresh_test;
+REINDEX TABLE maintain_test;
+REINDEX INDEX maintain_test_a_idx;
+REINDEX SCHEMA reindex_test;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS SHARE MODE;
+COMMIT;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS EXCLUSIVE MODE;
+COMMIT;
RESET ROLE;
-DROP TABLE vacanalyze_test;
-DROP ROLE regress_no_priv;
-DROP ROLE regress_only_vacuum;
-DROP ROLE regress_only_analyze;
-DROP ROLE regress_both;
-DROP ROLE regress_only_vacuum_all;
-DROP ROLE regress_only_analyze_all;
-DROP ROLE regress_both_all;
+DROP TABLE maintain_test;
+DROP MATERIALIZED VIEW refresh_test;
+DROP SCHEMA reindex_test;
+DROP ROLE regress_no_maintain;
+DROP ROLE regress_maintain;
+DROP ROLE regress_maintain_all;
USING (cid <> 44);
\dp
Access privileges
- Schema | Name | Type | Access privileges | Column privileges | Policies
---------------------+----------+-------+----------------------------------------------- +-------------------+--------------------------------------------
- regress_rls_schema | category | table | regress_rls_alice=arwdDxtvz /regress_rls_alice+| |
- | | | =arwdDxtvz /regress_rls_alice | |
- regress_rls_schema | document | table | regress_rls_alice=arwdDxtvz /regress_rls_alice+| | p1: +
- | | | =arwdDxtvz /regress_rls_alice | | (u): (dlevel <= ( SELECT uaccount.seclv +
- | | | | | FROM uaccount +
- | | | | | WHERE (uaccount.pguser = CURRENT_USER)))+
- | | | | | p2r (RESTRICTIVE): +
- | | | | | (u): ((cid <> 44) AND (cid < 50)) +
- | | | | | to: regress_rls_dave +
- | | | | | p1r (RESTRICTIVE): +
- | | | | | (u): (cid <> 44) +
- | | | | | to: regress_rls_dave
- regress_rls_schema | uaccount | table | regress_rls_alice=arwdDxtvz /regress_rls_alice+| |
- | | | =r/regress_rls_alice | |
+ Schema | Name | Type | Access privileges | Column privileges | Policies
+--------------------+----------+-------+----------------------------------------------+-------------------+--------------------------------------------
+ regress_rls_schema | category | table | regress_rls_alice=arwdDxtm /regress_rls_alice+| |
+ | | | =arwdDxtm /regress_rls_alice | |
+ regress_rls_schema | document | table | regress_rls_alice=arwdDxtm /regress_rls_alice+| | p1: +
+ | | | =arwdDxtm /regress_rls_alice | | (u): (dlevel <= ( SELECT uaccount.seclv +
+ | | | | | FROM uaccount +
+ | | | | | WHERE (uaccount.pguser = CURRENT_USER)))+
+ | | | | | p2r (RESTRICTIVE): +
+ | | | | | (u): ((cid <> 44) AND (cid < 50)) +
+ | | | | | to: regress_rls_dave +
+ | | | | | p1r (RESTRICTIVE): +
+ | | | | | (u): (cid <> 44) +
+ | | | | | to: regress_rls_dave
+ regress_rls_schema | uaccount | table | regress_rls_alice=arwdDxtm /regress_rls_alice+| |
+ | | | =r/regress_rls_alice | |
(3 rows)
\d document
VACUUM (ANALYZE) vacowned_parted;
WARNING: permission denied to vacuum "vacowned_parted", skipping it
WARNING: permission denied to vacuum "vacowned_part1", skipping it
-WARNING: permission denied to analyze "vacowned_part1", skipping it
WARNING: permission denied to vacuum "vacowned_part2", skipping it
-WARNING: permission denied to analyze "vacowned_part2", skipping it
VACUUM (ANALYZE) vacowned_part1;
WARNING: permission denied to vacuum "vacowned_part1", skipping it
VACUUM (ANALYZE) vacowned_part2;
WARNING: permission denied to analyze "vacowned_part2", skipping it
VACUUM (ANALYZE) vacowned_parted;
WARNING: permission denied to vacuum "vacowned_part2", skipping it
-WARNING: permission denied to analyze "vacowned_part2", skipping it
VACUUM (ANALYZE) vacowned_part1;
VACUUM (ANALYZE) vacowned_part2;
WARNING: permission denied to vacuum "vacowned_part2", skipping it
VACUUM (ANALYZE) vacowned_parted;
WARNING: permission denied to vacuum "vacowned_parted", skipping it
WARNING: permission denied to vacuum "vacowned_part2", skipping it
-WARNING: permission denied to analyze "vacowned_part2", skipping it
VACUUM (ANALYZE) vacowned_part1;
VACUUM (ANALYZE) vacowned_part2;
WARNING: permission denied to vacuum "vacowned_part2", skipping it
WARNING: permission denied to analyze "vacowned_part2", skipping it
VACUUM (ANALYZE) vacowned_parted;
WARNING: permission denied to vacuum "vacowned_part1", skipping it
-WARNING: permission denied to analyze "vacowned_part1", skipping it
WARNING: permission denied to vacuum "vacowned_part2", skipping it
-WARNING: permission denied to analyze "vacowned_part2", skipping it
VACUUM (ANALYZE) vacowned_part1;
WARNING: permission denied to vacuum "vacowned_part1", skipping it
VACUUM (ANALYZE) vacowned_part2;
DROP GROUP regress_dep_group;
-- can't drop the user if we revoke the privileges partially
-REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, VACUUM, ANALYZE ON deptest FROM regress_dep_user;
+REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, MAINTAIN ON deptest FROM regress_dep_user;
DROP USER regress_dep_user;
-- now we are OK to drop him
DROP ROLE regress_roleoption_donor;
DROP ROLE regress_roleoption_recipient;
--- VACUUM and ANALYZE
-CREATE ROLE regress_no_priv;
-CREATE ROLE regress_only_vacuum;
-CREATE ROLE regress_only_analyze;
-CREATE ROLE regress_both;
-CREATE ROLE regress_only_vacuum_all IN ROLE pg_vacuum_all_tables;
-CREATE ROLE regress_only_analyze_all IN ROLE pg_analyze_all_tables;
-CREATE ROLE regress_both_all IN ROLE pg_vacuum_all_tables, pg_analyze_all_tables;
-
-CREATE TABLE vacanalyze_test (a INT);
-GRANT VACUUM ON vacanalyze_test TO regress_only_vacuum, regress_both;
-GRANT ANALYZE ON vacanalyze_test TO regress_only_analyze, regress_both;
-
-SET ROLE regress_no_priv;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
-RESET ROLE;
-
-SET ROLE regress_only_vacuum;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
-RESET ROLE;
-
-SET ROLE regress_only_analyze;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
-RESET ROLE;
-
-SET ROLE regress_both;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
-RESET ROLE;
-
-SET ROLE regress_only_vacuum_all;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
+-- MAINTAIN
+CREATE ROLE regress_no_maintain;
+CREATE ROLE regress_maintain;
+CREATE ROLE regress_maintain_all IN ROLE pg_maintain;
+
+CREATE TABLE maintain_test (a INT);
+CREATE INDEX ON maintain_test (a);
+GRANT MAINTAIN ON maintain_test TO regress_maintain;
+CREATE MATERIALIZED VIEW refresh_test AS SELECT 1;
+GRANT MAINTAIN ON refresh_test TO regress_maintain;
+CREATE SCHEMA reindex_test;
+
+-- negative tests; should fail
+SET ROLE regress_no_maintain;
+VACUUM maintain_test;
+ANALYZE maintain_test;
+VACUUM (ANALYZE) maintain_test;
+CLUSTER maintain_test USING maintain_test_a_idx;
+REFRESH MATERIALIZED VIEW refresh_test;
+REINDEX TABLE maintain_test;
+REINDEX INDEX maintain_test_a_idx;
+REINDEX SCHEMA reindex_test;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS SHARE MODE;
+COMMIT;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS EXCLUSIVE MODE;
+COMMIT;
RESET ROLE;
-SET ROLE regress_only_analyze_all;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
+SET ROLE regress_maintain;
+VACUUM maintain_test;
+ANALYZE maintain_test;
+VACUUM (ANALYZE) maintain_test;
+CLUSTER maintain_test USING maintain_test_a_idx;
+REFRESH MATERIALIZED VIEW refresh_test;
+REINDEX TABLE maintain_test;
+REINDEX INDEX maintain_test_a_idx;
+REINDEX SCHEMA reindex_test;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS SHARE MODE;
+COMMIT;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS EXCLUSIVE MODE;
+COMMIT;
RESET ROLE;
-SET ROLE regress_both_all;
-VACUUM vacanalyze_test;
-ANALYZE vacanalyze_test;
-VACUUM (ANALYZE) vacanalyze_test;
+SET ROLE regress_maintain_all;
+VACUUM maintain_test;
+ANALYZE maintain_test;
+VACUUM (ANALYZE) maintain_test;
+CLUSTER maintain_test USING maintain_test_a_idx;
+REFRESH MATERIALIZED VIEW refresh_test;
+REINDEX TABLE maintain_test;
+REINDEX INDEX maintain_test_a_idx;
+REINDEX SCHEMA reindex_test;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS SHARE MODE;
+COMMIT;
+BEGIN;
+LOCK TABLE maintain_test IN ACCESS EXCLUSIVE MODE;
+COMMIT;
RESET ROLE;
-DROP TABLE vacanalyze_test;
-DROP ROLE regress_no_priv;
-DROP ROLE regress_only_vacuum;
-DROP ROLE regress_only_analyze;
-DROP ROLE regress_both;
-DROP ROLE regress_only_vacuum_all;
-DROP ROLE regress_only_analyze_all;
-DROP ROLE regress_both_all;
+DROP TABLE maintain_test;
+DROP MATERIALIZED VIEW refresh_test;
+DROP SCHEMA reindex_test;
+DROP ROLE regress_no_maintain;
+DROP ROLE regress_maintain;
+DROP ROLE regress_maintain_all;