@@ -262,7 +262,9 @@ struct DropRelationCallbackState
262
262
#define ATT_COMPOSITE_TYPE 0x0010
263
263
#define ATT_FOREIGN_TABLE 0x0020
264
264
265
- static void truncate_check_rel (Relation rel );
265
+ static void truncate_check_rel (Oid relid , Form_pg_class reltuple );
266
+ static void truncate_check_perms (Oid relid , Form_pg_class reltuple );
267
+ static void truncate_check_activity (Relation rel );
266
268
static List * MergeAttributes (List * schema , List * supers , char relpersistence ,
267
269
List * * supOids , List * * supconstr , int * supOidCount );
268
270
static bool MergeCheckConstraint (List * constraints , char * name , Node * expr );
@@ -1018,7 +1020,11 @@ ExecuteTruncate(TruncateStmt *stmt)
1018
1020
heap_close (rel , lockmode );
1019
1021
continue ;
1020
1022
}
1021
- truncate_check_rel (rel );
1023
+
1024
+ truncate_check_rel (myrelid , rel -> rd_rel );
1025
+ truncate_check_perms (myrelid , rel -> rd_rel );
1026
+ truncate_check_activity (rel );
1027
+
1022
1028
rels = lappend (rels , rel );
1023
1029
relids = lappend_oid (relids , myrelid );
1024
1030
@@ -1054,7 +1060,15 @@ ExecuteTruncate(TruncateStmt *stmt)
1054
1060
continue ;
1055
1061
}
1056
1062
1057
- truncate_check_rel (rel );
1063
+ /*
1064
+ * Inherited TRUNCATE commands perform access
1065
+ * permission checks on the parent table only.
1066
+ * So we skip checking the children's permissions
1067
+ * and don't call truncate_check_perms() here.
1068
+ */
1069
+ truncate_check_rel (RelationGetRelid (rel ), rel -> rd_rel );
1070
+ truncate_check_activity (rel );
1071
+
1058
1072
rels = lappend (rels , rel );
1059
1073
relids = lappend_oid (relids , childrelid );
1060
1074
}
@@ -1088,7 +1102,9 @@ ExecuteTruncate(TruncateStmt *stmt)
1088
1102
ereport (NOTICE ,
1089
1103
(errmsg ("truncate cascades to table \"%s\"" ,
1090
1104
RelationGetRelationName (rel ))));
1091
- truncate_check_rel (rel );
1105
+ truncate_check_rel (relid , rel -> rd_rel );
1106
+ truncate_check_perms (relid , rel -> rd_rel );
1107
+ truncate_check_activity (rel );
1092
1108
rels = lappend (rels , rel );
1093
1109
relids = lappend_oid (relids , relid );
1094
1110
}
@@ -1289,30 +1305,45 @@ ExecuteTruncate(TruncateStmt *stmt)
1289
1305
* Check that a given rel is safe to truncate. Subroutine for ExecuteTruncate
1290
1306
*/
1291
1307
static void
1292
- truncate_check_rel (Relation rel )
1308
+ truncate_check_rel (Oid relid , Form_pg_class reltuple )
1293
1309
{
1294
- AclResult aclresult ;
1310
+ char * relname = NameStr ( reltuple -> relname ) ;
1295
1311
1296
1312
/* Only allow truncate on regular tables */
1297
- if (rel -> rd_rel -> relkind != RELKIND_RELATION )
1313
+ if (reltuple -> relkind != RELKIND_RELATION )
1298
1314
ereport (ERROR ,
1299
1315
(errcode (ERRCODE_WRONG_OBJECT_TYPE ),
1300
- errmsg ("\"%s\" is not a table" ,
1301
- RelationGetRelationName (rel ))));
1316
+ errmsg ("\"%s\" is not a table" , relname )));
1302
1317
1303
- /* Permissions checks */
1304
- aclresult = pg_class_aclcheck (RelationGetRelid (rel ), GetUserId (),
1305
- ACL_TRUNCATE );
1306
- if (aclresult != ACLCHECK_OK )
1307
- aclcheck_error (aclresult , ACL_KIND_CLASS ,
1308
- RelationGetRelationName (rel ));
1309
-
1310
- if (!allowSystemTableMods && IsSystemRelation (rel ))
1318
+ if (!allowSystemTableMods && IsSystemClass (relid , reltuple ))
1311
1319
ereport (ERROR ,
1312
1320
(errcode (ERRCODE_INSUFFICIENT_PRIVILEGE ),
1313
1321
errmsg ("permission denied: \"%s\" is a system catalog" ,
1314
- RelationGetRelationName (rel ))));
1322
+ relname )));
1323
+ }
1315
1324
1325
+ /*
1326
+ * Check that current user has the permission to truncate given relation.
1327
+ */
1328
+ static void
1329
+ truncate_check_perms (Oid relid , Form_pg_class reltuple )
1330
+ {
1331
+ char * relname = NameStr (reltuple -> relname );
1332
+ AclResult aclresult ;
1333
+
1334
+ /* Permissions checks */
1335
+ aclresult = pg_class_aclcheck (relid , GetUserId (), ACL_TRUNCATE );
1336
+ if (aclresult != ACLCHECK_OK )
1337
+ aclcheck_error (aclresult , ACL_KIND_CLASS , relname );
1338
+ }
1339
+
1340
+ /*
1341
+ * Set of extra sanity checks to check if a given relation is safe to
1342
+ * truncate.
1343
+ */
1344
+ static void
1345
+ truncate_check_activity (Relation rel )
1346
+ {
1316
1347
/*
1317
1348
* Don't allow truncate on temp tables of other backends ... their local
1318
1349
* buffer manager is not going to cope.
0 commit comments