|
41 | 41 | #include "catalog/pg_namespace.h" |
42 | 42 | #include "commands/cluster.h" |
43 | 43 | #include "commands/defrem.h" |
| 44 | +#include "commands/tablecmds.h" |
44 | 45 | #include "commands/vacuum.h" |
45 | 46 | #include "miscadmin.h" |
46 | 47 | #include "nodes/makefuncs.h" |
@@ -91,7 +92,8 @@ static void vac_truncate_clog(TransactionId frozenXID, |
91 | 92 | MultiXactId minMulti, |
92 | 93 | TransactionId lastSaneFrozenXid, |
93 | 94 | MultiXactId lastSaneMinMulti); |
94 | | -static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params); |
| 95 | +static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, |
| 96 | + bool skip_privs); |
95 | 97 | static double compute_parallel_delay(void); |
96 | 98 | static VacOptValue get_vacoptval_from_boolean(DefElem *def); |
97 | 99 | static bool vac_tid_reaped(ItemPointer itemptr, void *state); |
@@ -501,7 +503,7 @@ vacuum(List *relations, VacuumParams *params, |
501 | 503 |
|
502 | 504 | if (params->options & VACOPT_VACUUM) |
503 | 505 | { |
504 | | - if (!vacuum_rel(vrel->oid, vrel->relation, params)) |
| 506 | + if (!vacuum_rel(vrel->oid, vrel->relation, params, false)) |
505 | 507 | continue; |
506 | 508 | } |
507 | 509 |
|
@@ -598,11 +600,13 @@ vacuum_is_permitted_for_relation(Oid relid, Form_pg_class reltuple, |
598 | 600 | * - the role owns the relation |
599 | 601 | * - the role owns the current database and the relation is not shared |
600 | 602 | * - the role has been granted the MAINTAIN privilege on the relation |
| 603 | + * - the role has privileges to vacuum/analyze any of the relation's |
| 604 | + * partition ancestors |
601 | 605 | *---------- |
602 | 606 | */ |
603 | | - if (object_ownercheck(RelationRelationId, relid, GetUserId()) || |
604 | | - (object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) && !reltuple->relisshared) || |
605 | | - pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) == ACLCHECK_OK) |
| 607 | + if ((object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) && !reltuple->relisshared) || |
| 608 | + pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) == ACLCHECK_OK || |
| 609 | + has_partition_ancestor_privs(relid, GetUserId(), ACL_MAINTAIN)) |
606 | 610 | return true; |
607 | 611 |
|
608 | 612 | relname = NameStr(reltuple->relname); |
@@ -1828,7 +1832,7 @@ vac_truncate_clog(TransactionId frozenXID, |
1828 | 1832 | * At entry and exit, we are not inside a transaction. |
1829 | 1833 | */ |
1830 | 1834 | static bool |
1831 | | -vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params) |
| 1835 | +vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, bool skip_privs) |
1832 | 1836 | { |
1833 | 1837 | LOCKMODE lmode; |
1834 | 1838 | Relation rel; |
@@ -1915,7 +1919,8 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params) |
1915 | 1919 | * happen across multiple transactions where privileges could have changed |
1916 | 1920 | * in-between. Make sure to only generate logs for VACUUM in this case. |
1917 | 1921 | */ |
1918 | | - if (!vacuum_is_permitted_for_relation(RelationGetRelid(rel), |
| 1922 | + if (!skip_privs && |
| 1923 | + !vacuum_is_permitted_for_relation(RelationGetRelid(rel), |
1919 | 1924 | rel->rd_rel, |
1920 | 1925 | params->options & VACOPT_VACUUM)) |
1921 | 1926 | { |
@@ -2089,7 +2094,7 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params) |
2089 | 2094 | * totally unimportant for toast relations. |
2090 | 2095 | */ |
2091 | 2096 | if (toast_relid != InvalidOid) |
2092 | | - vacuum_rel(toast_relid, NULL, params); |
| 2097 | + vacuum_rel(toast_relid, NULL, params, true); |
2093 | 2098 |
|
2094 | 2099 | /* |
2095 | 2100 | * Now release the session-level lock on the main table. |
|
0 commit comments