@@ -304,6 +304,7 @@ struct DropRelationCallbackState
304
304
((child_is_partition) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL)
305
305
306
306
static void truncate_check_rel(Oid relid, Form_pg_class reltuple);
307
+ static void truncate_check_perms(Oid relid, Form_pg_class reltuple);
307
308
static void truncate_check_activity(Relation rel);
308
309
static void RangeVarCallbackForTruncate(const RangeVar *relation,
309
310
Oid relId, Oid oldRelId, void *arg);
@@ -1615,6 +1616,12 @@ ExecuteTruncate(TruncateStmt *stmt)
1615
1616
continue;
1616
1617
}
1617
1618
1619
+ /*
1620
+ * Inherited TRUNCATE commands perform access
1621
+ * permission checks on the parent table only.
1622
+ * So we skip checking the children's permissions
1623
+ * and don't call truncate_check_perms() here.
1624
+ */
1618
1625
truncate_check_rel(RelationGetRelid(rel), rel->rd_rel);
1619
1626
truncate_check_activity(rel);
1620
1627
@@ -1701,6 +1708,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
1701
1708
(errmsg("truncate cascades to table \"%s\"",
1702
1709
RelationGetRelationName(rel))));
1703
1710
truncate_check_rel(relid, rel->rd_rel);
1711
+ truncate_check_perms(relid, rel->rd_rel);
1704
1712
truncate_check_activity(rel);
1705
1713
rels = lappend(rels, rel);
1706
1714
relids = lappend_oid(relids, relid);
@@ -1951,7 +1959,6 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
1951
1959
static void
1952
1960
truncate_check_rel(Oid relid, Form_pg_class reltuple)
1953
1961
{
1954
- AclResult aclresult;
1955
1962
char *relname = NameStr(reltuple->relname);
1956
1963
1957
1964
/*
@@ -1965,12 +1972,6 @@ truncate_check_rel(Oid relid, Form_pg_class reltuple)
1965
1972
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1966
1973
errmsg("\"%s\" is not a table", relname)));
1967
1974
1968
- /* Permissions checks */
1969
- aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_TRUNCATE);
1970
- if (aclresult != ACLCHECK_OK)
1971
- aclcheck_error(aclresult, get_relkind_objtype(reltuple->relkind),
1972
- relname);
1973
-
1974
1975
if (!allowSystemTableMods && IsSystemClass(relid, reltuple))
1975
1976
ereport(ERROR,
1976
1977
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -1980,6 +1981,22 @@ truncate_check_rel(Oid relid, Form_pg_class reltuple)
1980
1981
InvokeObjectTruncateHook(relid);
1981
1982
}
1982
1983
1984
+ /*
1985
+ * Check that current user has the permission to truncate given relation.
1986
+ */
1987
+ static void
1988
+ truncate_check_perms(Oid relid, Form_pg_class reltuple)
1989
+ {
1990
+ char *relname = NameStr(reltuple->relname);
1991
+ AclResult aclresult;
1992
+
1993
+ /* Permissions checks */
1994
+ aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_TRUNCATE);
1995
+ if (aclresult != ACLCHECK_OK)
1996
+ aclcheck_error(aclresult, get_relkind_objtype(reltuple->relkind),
1997
+ relname);
1998
+ }
1999
+
1983
2000
/*
1984
2001
* Set of extra sanity checks to check if a given relation is safe to
1985
2002
* truncate. This is split with truncate_check_rel() as
@@ -15292,6 +15309,7 @@ RangeVarCallbackForTruncate(const RangeVar *relation,
15292
15309
elog(ERROR, "cache lookup failed for relation %u", relId);
15293
15310
15294
15311
truncate_check_rel(relId, (Form_pg_class) GETSTRUCT(tuple));
15312
+ truncate_check_perms(relId, (Form_pg_class) GETSTRUCT(tuple));
15295
15313
15296
15314
ReleaseSysCache(tuple);
15297
15315
}
0 commit comments