@@ -302,6 +302,7 @@ struct DropRelationCallbackState
302
302
((child_is_partition) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL)
303
303
304
304
static void truncate_check_rel(Oid relid, Form_pg_class reltuple);
305
+ static void truncate_check_perms(Oid relid, Form_pg_class reltuple);
305
306
static void truncate_check_activity(Relation rel);
306
307
static void RangeVarCallbackForTruncate(const RangeVar *relation,
307
308
Oid relId, Oid oldRelId, void *arg);
@@ -1590,6 +1591,12 @@ ExecuteTruncate(TruncateStmt *stmt)
1590
1591
continue;
1591
1592
}
1592
1593
1594
+ /*
1595
+ * Inherited TRUNCATE commands perform access
1596
+ * permission checks on the parent table only.
1597
+ * So we skip checking the children's permissions
1598
+ * and don't call truncate_check_perms() here.
1599
+ */
1593
1600
truncate_check_rel(RelationGetRelid(rel), rel->rd_rel);
1594
1601
truncate_check_activity(rel);
1595
1602
@@ -1676,6 +1683,7 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
1676
1683
(errmsg("truncate cascades to table \"%s\"",
1677
1684
RelationGetRelationName(rel))));
1678
1685
truncate_check_rel(relid, rel->rd_rel);
1686
+ truncate_check_perms(relid, rel->rd_rel);
1679
1687
truncate_check_activity(rel);
1680
1688
rels = lappend(rels, rel);
1681
1689
relids = lappend_oid(relids, relid);
@@ -1926,7 +1934,6 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
1926
1934
static void
1927
1935
truncate_check_rel(Oid relid, Form_pg_class reltuple)
1928
1936
{
1929
- AclResult aclresult;
1930
1937
char *relname = NameStr(reltuple->relname);
1931
1938
1932
1939
/*
@@ -1940,19 +1947,29 @@ truncate_check_rel(Oid relid, Form_pg_class reltuple)
1940
1947
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1941
1948
errmsg("\"%s\" is not a table", relname)));
1942
1949
1943
- /* Permissions checks */
1944
- aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_TRUNCATE);
1945
- if (aclresult != ACLCHECK_OK)
1946
- aclcheck_error(aclresult, get_relkind_objtype(reltuple->relkind),
1947
- relname);
1948
-
1949
1950
if (!allowSystemTableMods && IsSystemClass(relid, reltuple))
1950
1951
ereport(ERROR,
1951
1952
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1952
1953
errmsg("permission denied: \"%s\" is a system catalog",
1953
1954
relname)));
1954
1955
}
1955
1956
1957
+ /*
1958
+ * Check that current user has the permission to truncate given relation.
1959
+ */
1960
+ static void
1961
+ truncate_check_perms(Oid relid, Form_pg_class reltuple)
1962
+ {
1963
+ char *relname = NameStr(reltuple->relname);
1964
+ AclResult aclresult;
1965
+
1966
+ /* Permissions checks */
1967
+ aclresult = pg_class_aclcheck(relid, GetUserId(), ACL_TRUNCATE);
1968
+ if (aclresult != ACLCHECK_OK)
1969
+ aclcheck_error(aclresult, get_relkind_objtype(reltuple->relkind),
1970
+ relname);
1971
+ }
1972
+
1956
1973
/*
1957
1974
* Set of extra sanity checks to check if a given relation is safe to
1958
1975
* truncate. This is split with truncate_check_rel() as
@@ -14886,6 +14903,7 @@ RangeVarCallbackForTruncate(const RangeVar *relation,
14886
14903
elog(ERROR, "cache lookup failed for relation %u", relId);
14887
14904
14888
14905
truncate_check_rel(relId, (Form_pg_class) GETSTRUCT(tuple));
14906
+ truncate_check_perms(relId, (Form_pg_class) GETSTRUCT(tuple));
14889
14907
14890
14908
ReleaseSysCache(tuple);
14891
14909
}
0 commit comments