From 5363c4781a5df358ae1765f0517ad1ff21de79ed Mon Sep 17 00:00:00 2001 From: Fariha Shaikh Date: Wed, 28 Jan 2026 22:09:36 +0000 Subject: [PATCH] MDEV-37948 ALTER TABLE TRUNCATE PARTITION requires only DROP privilege ALTER TABLE ... TRUNCATE PARTITION only checks for DROP privilege, while ALTER TABLE ... DROP PARTITION correctly requires both DROP and ALTER privileges. This is inconsistent and a privilege issue since TRUNCATE PARTITION is an ALTER TABLE statement. Add ALTER privilege check to TRUNCATE PARTITION to match DROP PARTITION behavior and documentation. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services, Inc. --- mysql-test/main/partition_grant.result | 23 ++++++++++++++++++++++ mysql-test/main/partition_grant.test | 27 ++++++++++++++++++++++++++ sql/sql_partition_admin.cc | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/partition_grant.result b/mysql-test/main/partition_grant.result index c269896975db8..8f7ced3cafb58 100644 --- a/mysql-test/main/partition_grant.result +++ b/mysql-test/main/partition_grant.result @@ -46,6 +46,29 @@ ERROR HY000: Table has no partition for value 1 disconnect conn5; connection default; drop table t1; +# +# MDEV-37948: ALTER TABLE ... TRUNCATE PARTITION should require ALTER privilege +# +create table t1 (a int) partition by list (a) (partition p1 values in (1), partition p2 values in (2), partition p3 values in (3)); +insert into t1 values (1),(2),(3); +revoke all privileges on mysqltest_1.* from mysqltest_1@localhost; +grant drop on mysqltest_1.* to mysqltest_1@localhost; +connect conn6,localhost,mysqltest_1,,mysqltest_1; +show grants for current_user; +Grants for mysqltest_1@localhost +GRANT USAGE ON *.* TO `mysqltest_1`@`localhost` +GRANT DROP ON `mysqltest_1`.* TO `mysqltest_1`@`localhost` +alter table t1 truncate partition p1; +ERROR 42000: ALTER command denied to user 'mysqltest_1'@'localhost' for table `mysqltest_1`.`t1` +disconnect conn6; +connection default; +grant alter on mysqltest_1.* to mysqltest_1@localhost; +connect conn7,localhost,mysqltest_1,,mysqltest_1; +alter table t1 truncate partition p1; +disconnect conn7; +connection default; +revoke alter, drop on mysqltest_1.* from mysqltest_1@localhost; +drop table t1; drop user mysqltest_1@localhost; drop schema mysqltest_1; End of 5.1 tests diff --git a/mysql-test/main/partition_grant.test b/mysql-test/main/partition_grant.test index a5df218bb1038..895a139266f14 100644 --- a/mysql-test/main/partition_grant.test +++ b/mysql-test/main/partition_grant.test @@ -76,6 +76,33 @@ disconnect conn5; connection default; drop table t1; +--echo # +--echo # MDEV-37948: ALTER TABLE ... TRUNCATE PARTITION should require ALTER privilege +--echo # + +create table t1 (a int) partition by list (a) (partition p1 values in (1), partition p2 values in (2), partition p3 values in (3)); +insert into t1 values (1),(2),(3); + +revoke all privileges on mysqltest_1.* from mysqltest_1@localhost; +grant drop on mysqltest_1.* to mysqltest_1@localhost; + +connect (conn6,localhost,mysqltest_1,,mysqltest_1); +show grants for current_user; +--error ER_TABLEACCESS_DENIED_ERROR +alter table t1 truncate partition p1; +disconnect conn6; + +connection default; +grant alter on mysqltest_1.* to mysqltest_1@localhost; + +connect (conn7,localhost,mysqltest_1,,mysqltest_1); +alter table t1 truncate partition p1; +disconnect conn7; + +connection default; +revoke alter, drop on mysqltest_1.* from mysqltest_1@localhost; +drop table t1; + drop user mysqltest_1@localhost; drop schema mysqltest_1; diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 6697b4f580e78..4d47e667648e7 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -869,7 +869,7 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) write the statement to the binary log if necessary. */ - if (check_one_table_access(thd, DROP_ACL, first_table)) + if (check_one_table_access(thd, DROP_ACL | ALTER_ACL, first_table)) DBUG_RETURN(TRUE); #ifdef WITH_WSREP