MDEV-36280 ALTER TABLE with DEFAULT NEXTVAL(sequence) fails due to

insufficient grants

Defer privilege checking until fix_fields. This way ALTER will behave
consistently with CREATE, and require the same privileges to sequence
column (SELECT/INSERT)
This commit is contained in:
Vladislav Vaintroub 2025-06-03 10:32:22 +02:00
parent 643319a7fb
commit 888663ce12
3 changed files with 40 additions and 3 deletions

View File

@ -97,6 +97,19 @@ ERROR 42000: SELECT, INSERT command denied to user 'u'@'localhost' for table `my
disconnect con1;
connection default;
drop user u;
create user u_alter;
create table t1 (id int);
grant alter on t1 to u_alter;
connect con_alter,localhost,u_alter,,mysqltest_1;
alter table t1 modify id int default nextval(s1);
ERROR 42000: SELECT, INSERT command denied to user 'u_alter'@'localhost' for table `mysqltest_1`.`s1`
connection default;
grant insert, select on s1 to u_alter;
connection con_alter;
alter table t1 modify id int default nextval(s1);
disconnect con_alter;
connection default;
drop user u_alter;
drop database mysqltest_1;
#
# End of 10.11 tests

View File

@ -106,6 +106,22 @@ create table t1 (a int not null default(nextval(s1)),
--connection default
drop user u;
# ALTER for table with DEFAULT NEXTVAL(seq) column needs INSERT/SELECT on seq
# just like CREATE does in the example above
create user u_alter;
create table t1 (id int);
grant alter on t1 to u_alter;
--connect(con_alter,localhost,u_alter,,mysqltest_1)
--error ER_TABLEACCESS_DENIED_ERROR
alter table t1 modify id int default nextval(s1);
--connection default
grant insert, select on s1 to u_alter;
--connection con_alter
alter table t1 modify id int default nextval(s1);
--disconnect con_alter
--connection default
drop user u_alter;
#
# Cleanup
#

View File

@ -8347,9 +8347,17 @@ bool check_grant(THD *thd, privilege_t want_access, TABLE_LIST *tables,
Direct SELECT of a sequence table doesn't set t_ref->sequence, so
privileges will be checked normally, as for any table.
*/
if (t_ref->sequence &&
!(want_access & ~(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL)))
continue;
if (t_ref->sequence)
{
if (!(want_access & ~(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL)))
continue;
/*
If it is ALTER..SET DEFAULT= nextval(sequence), also defer checks
until ::fix_fields().
*/
if (tl != tables && want_access == ALTER_ACL)
continue;
}
const ACL_internal_table_access *access=
get_cached_table_access(&t_ref->grant.m_internal,